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 ValheimLocalCoOp v1.0.16
ValheimLocalCoop.dll
Decompiled 2 days 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.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.UI; using UnityEngine.InputSystem.Utilities; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.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; } } } namespace ValheimLocalCoop { public enum SplitMode { SideBySide, TopBottom } public enum P1Device { KeyboardMouse, Gamepad0 } public enum FrameMode { GameFramebuffer, ScreenRect } public enum HudMode { FitToViewport, LeaveFullScreen } public enum P2HudMode { Mirror, Simple } public enum WheelMouseMode { PointerFix, Off, VirtualStick } [BepInPlugin("dev.example.valheim.localcoop", "Valheim Local Co-op", "1.0.16")] public class SplitScreenPlugin : BaseUnityPlugin { public const string Guid = "dev.example.valheim.localcoop"; public const string Name = "Valheim Local Co-op"; public const string Version = "1.0.16"; internal static ManualLogSource Log; internal static ConfigEntry<SplitMode> Mode; internal static ConfigEntry<FrameMode> Frame; internal static ConfigEntry<HudMode> P1Hud; internal static ConfigEntry<P1Device> Player1Device; internal static ConfigEntry<KeyboardShortcut> ToggleKey; internal static ConfigEntry<float> LeashDistance; internal static ConfigEntry<KeyboardShortcut> RescueKey; internal static ConfigEntry<bool> Player2Audio; internal static ConfigEntry<int> Player2AreaReduction; internal static ConfigEntry<bool> GrassAroundBothPlayers; internal static ConfigEntry<WheelMouseMode> WheelMouse; internal static ConfigEntry<bool> MouseHelpsP2; internal static ConfigEntry<bool> RouteSharedInput; internal static ConfigEntry<float> RespawnDelay; internal static ConfigEntry<float> CameraDistance; internal static ConfigEntry<bool> InvertStickY; internal static ConfigEntry<bool> InvertLookY; internal static ConfigEntry<int> Pad1Index; internal static ConfigEntry<int> Pad2Index; internal static ConfigEntry<KeyboardShortcut> DebugKey; internal static ConfigEntry<bool> AskForDevices; internal static ConfigEntry<P2HudMode> Player2Hud; internal static ConfigEntry<float> InventoryScale; internal static ConfigEntry<bool> SeparateInventories; internal static ConfigEntry<bool> AskForCharacter; internal static ConfigEntry<string> LastP2Character; internal static ConfigEntry<KeyboardShortcut> AppearanceKey; internal static ConfigEntry<float> ExtraGrassDistance; internal static ConfigEntry<bool> PerPlayerNameplates; internal static ConfigEntry<bool> WorldAroundBothPlayers; private Harmony _harmony; private bool _showDebug; private bool _spyPatched; private void Awake() { //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: 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_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Mode = ((BaseUnityPlugin)this).Config.Bind<SplitMode>("Layout", "SplitMode", SplitMode.SideBySide, "Viewport arrangement."); Frame = ((BaseUnityPlugin)this).Config.Bind<FrameMode>("Layout", "FrameMode", FrameMode.GameFramebuffer, "GameFramebuffer: reuse the game's own framebuffer (recommended for Valheim 1.0). ScreenRect: Camera.rect fallback."); P1Hud = ((BaseUnityPlugin)this).Config.Bind<HudMode>("Layout", "Player1Hud", HudMode.FitToViewport, "FitToViewport: squeeze P1's real HUD into its half. LeaveFullScreen: leave it untouched."); Player2Hud = ((BaseUnityPlugin)this).Config.Bind<P2HudMode>("Layout", "Player2Hud", P2HudMode.Mirror, "Mirror (experimental): the game's real HUD is drawn twice per frame, once per player. Simple: a small HUD drawn by this plugin for P2 (use if Mirror misbehaves)."); InventoryScale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "InventoryScale", 0.8f, "Scale of the inventory window while split (it is placed in the half of the player who opened it)."); SeparateInventories = ((BaseUnityPlugin)this).Config.Bind<bool>("Layout", "SeparateInventories", true, "true: Player 2 gets their own copy of the real inventory window (both can be open at once). false: one shared window + a simple backpack window for the other player."); AskForCharacter = ((BaseUnityPlugin)this).Config.Bind<bool>("Characters", "AskForCharacter", true, "After choosing devices, Player 2 picks an existing character, makes a new one, or plays as a guest."); LastP2Character = ((BaseUnityPlugin)this).Config.Bind<string>("Characters", "LastPlayer2Character", "", "Remembered automatically."); AppearanceKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Characters", "AppearanceKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Opens the appearance panel (body, hair, beard, colours, name, costume). Use the mouse."); ExtraGrassDistance = ((BaseUnityPlugin)this).Config.Bind<float>("World", "ExtraGrassDistance", 50f, "How far (meters) the grass radius may grow so grass also covers Player 2. 0 = off. Higher costs FPS."); WorldAroundBothPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("World", "WorldAroundBothPlayers", true, "Load objects, zones and creature AI around Player 2 as well as Player 1."); PerPlayerNameplates = ((BaseUnityPlugin)this).Config.Bind<bool>("Layout", "PerPlayerNameplates", true, "Give Player 2 their own enemy/player name plates (a copy of the game's name-plate overlay)."); Player1Device = ((BaseUnityPlugin)this).Config.Bind<P1Device>("Input", "Player1Device", P1Device.KeyboardMouse, "KeyboardMouse: P1 ignores pads. Gamepad0: P1 uses a gamepad."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "JoinLeaveKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), "Join/leave key."); InvertStickY = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "InvertStickY", true, "Only for the legacy single-axis stick methods. Flip if P2 moves inverted."); InvertLookY = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "InvertLookY", false, "Flip P2's vertical look if it feels inverted."); Pad1Index = ((BaseUnityPlugin)this).Config.Bind<int>("Input", "Player1PadIndex", 0, "Gamepad index (0-3) used by P1 when P1Device = Gamepad0."); Pad2Index = ((BaseUnityPlugin)this).Config.Bind<int>("Input", "Player2PadIndex", 1, "Gamepad index (0-3) used by P2. If fewer pads are connected, the last connected pad is used."); LeashDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Co-op", "TetherDistance", 200f, "Meters. Beyond this, Player 2 vanishes in a puff of smoke and reappears next to Player 1. 0 = off (not recommended)."); RescueKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Co-op", "RescueKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Pull Player 2 next to Player 1 and repair Player 1's view (black screen etc.)."); Player2Audio = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Player2Sounds", true, "Each player hears the action sounds nearest to them (footsteps, combat, cooking, bows ...) from their own point of view, in 3D. Music and ambience are shared."); Player2AreaReduction = ((BaseUnityPlugin)this).Config.Bind<int>("World", "Player2AreaReduction", 0, "Load a smaller area around Player 2 (in zones) to save performance when far apart. 0 = same as Player 1."); RouteSharedInput = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "RouteSharedInput", true, "Game code that doesn't belong to either player (menu buttons, build-menu tabs and close buttons ...) only hears ONE controller: the build menu's owner while it is open, otherwise Player 1. Turn off only if some menu stops reacting to Player 1's controller."); MouseHelpsP2 = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "MouseCanHelpPlayer2", true, "The mouse belongs to Player 1, but can also drag and sort items in Player 2's open inventory. Also switchable on the F10 setup screen and in the F8 panel."); WheelMouse = ((BaseUnityPlugin)this).Config.Bind<WheelMouseMode>("Input", "WheelMouseMode", WheelMouseMode.PointerFix, "How the keyboard player's mouse drives the radial wheels (G / T). PointerFix: re-centre the mouse on that player's half. Off: the game's own handling. VirtualStick: turn mouse movement into a stick, like a controller."); GrassAroundBothPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("World", "GrassAroundBothPlayers", true, "Give Player 2 their own normal-radius grass when far from Player 1 (instead of one huge grass circle)."); RespawnDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Co-op", "RespawnDelay", 10f, "Seconds before P2 respawns near P1."); CameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "P2CameraDistance", 3.5f, "Third-person distance for P2."); AskForDevices = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "AskForDevices", true, "true: F10 opens a setup screen where each player presses a key/button on the device they want (like Project Zomboid). false: use Player1Device / pad indices below without asking."); DebugKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "DebugKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggles the debug overlay and dumps diagnostics + a spy on ZInput calls to the log."); _harmony = new Harmony("dev.example.valheim.localcoop"); Type[] types = typeof(SplitScreenPlugin).Assembly.GetTypes(); foreach (Type type in types) { if (!(type == typeof(ZInput_Spy))) { try { _harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogError((object)("Patch class failed: " + type.Name + " -> " + ex.Message)); } } } Log.LogInfo((object)"Valheim Local Co-op 1.0.16 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) LocalPlayerManager.TrackPrimary(); InvClone.TickRestore(); NameplateCopy.Ui.TickRestore(); GrassCopy.TickRestore(); RadialCopy.TickRestore(); KeyboardShortcut value = DebugKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _showDebug = !_showDebug; if (_showDebug && !_spyPatched) { _spyPatched = true; try { _harmony.CreateClassProcessor(typeof(ZInput_Spy)).Patch(); } catch (Exception ex) { Log.LogError((object)("Input spy failed (continuing without it): " + ex.Message)); } } Diagnostics.SpyOn = _showDebug; if (_showDebug) { Diagnostics.Dump(); if (LocalPlayerManager.Joined) { SplitCheck.Run(always: true); } } } if ((Object)(object)Game.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { DevicePicker.Cancel(); if (LocalPlayerManager.Joined) { LocalPlayerManager.Leave(); } return; } value = ToggleKey.Value; bool flag = ((KeyboardShortcut)(ref value)).IsDown(); Player val = LocalPlayerManager.Players[0]; SetupUi.Update(); VMenus.Update(); if (DevicePicker.Active) { if (flag || (Object)(object)val == (Object)null) { DevicePicker.Cancel(); } else if (DevicePicker.Poll()) { AfterDevices(val); } } else if (CharacterPicker.Active) { if (flag || (Object)(object)val == (Object)null) { CharacterPicker.Cancel(); } else if (CharacterPicker.Poll()) { LocalPlayerManager.Join(val); } } else if (!LocalPlayerManager.Joined) { bool flag2 = !AskForDevices.Value && Pads.Down(Pads.Resolve(Pad2Index.Value), 16); if ((Object)(object)val != (Object)null && (flag || flag2)) { if (AskForDevices.Value) { DevicePicker.Begin(); } else { DeviceMap.ApplyDefaults(); AfterDevices(val); } } } else if (flag) { LocalPlayerManager.Leave(); } AppearanceUi.Update(); if (LocalPlayerManager.Joined) { value = RescueKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Rescue.Run(); } Rescue.Watchdog(); SplitCheck.Tick(); MouseUse.Tick(); MenuNav.Tick(); P2Build.Tick(); if ((Object)(object)val != (Object)null) { LocalPlayerManager.Tick(val); } SplitLayout.Tick(); GameBindings.PollAll(); Backpack.UpdateInput(); DragPanels.Update(); WorldPriority.Tick(); RadialCopy.TrackOwnerFromInput(); WheelMouseState.Tick(); Diagnostics.WheelProbe(); AudioProxy.Tick(); } else { AudioProxy.Clear(); } } private void AfterDevices(Player p1) { if (AskForCharacter.Value) { CharacterPicker.Begin(); return; } CharacterSlot.SetPending(null, null); LocalPlayerManager.Join(p1); } private void LateUpdate() { Costume.Tick(); if (LocalPlayerManager.Joined) { SplitLayout.Reassert(); HudMirror.Render(); } } private void OnGUI() { //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: 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_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) P2Hud.Draw(); Backpack.Draw(); P2Build.Draw(); if (_showDebug) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("SPLITSCREEN DEBUG v1.0.16 (F9 hides)"); stringBuilder.AppendLine("Joined=" + LocalPlayerManager.Joined + " ActiveSlot=" + LocalPlayerManager.ActiveSlot + " ctxDepth=" + LocalPlayerManager.Depth + " (should be 0 / 0 here)"); stringBuilder.AppendLine("Gamepads seen by Input System: " + Pads.Count); for (int i = 0; i < Mathf.Max(1, Mathf.Min(Pads.Count, 4)); i++) { Pads.Snapshot snapshot = Pads.Cur(i); stringBuilder.AppendLine("pad" + i + ": " + (snapshot.Connected ? "CONNECTED" : "-") + " btn=" + snapshot.Buttons.ToString("X") + " L=(" + snapshot.LX.ToString("F2") + "," + snapshot.LY.ToString("F2") + ") R=(" + snapshot.RX.ToString("F2") + "," + snapshot.RY.ToString("F2") + ")"); } Player val = LocalPlayerManager.Players[0]; Player val2 = LocalPlayerManager.Players[1]; object obj; Vector3 position; if (!((Object)(object)val != (Object)null)) { obj = "none"; } else { position = ((Component)val).transform.position; obj = ((Vector3)(ref position)).ToString("F1"); } object obj2; if (!((Object)(object)val2 != (Object)null)) { obj2 = "none"; } else { position = ((Component)val2).transform.position; obj2 = ((Vector3)(ref position)).ToString("F1"); } stringBuilder.AppendLine("P1: " + (string?)obj + " P2: " + (string?)obj2); stringBuilder.AppendLine("Cursor: lock=" + ((object)Cursor.lockState/*cast due to .constrained prefix*/).ToString() + " visible=" + Cursor.visible); stringBuilder.AppendLine("Frame=" + Frame.Value.ToString() + " P1Hud=" + P1Hud.Value.ToString() + " " + SplitLayout.Describe()); stringBuilder.AppendLine("Devices: P1=" + DeviceMap.Label(0) + " P2=" + DeviceMap.Label(1) + " Ask=" + AskForDevices.Value); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(10f, 10f, 760f, 220f); GUI.Box(val3, GUIContent.none); GUI.Label(val3, stringBuilder.ToString()); } } } internal static class Pads { public struct Snapshot { public bool Connected; public ushort Buttons; public float LX; public float LY; public float RX; public float RY; public float LT; public float RT; public bool Has(ushort mask) { return (Buttons & mask) != 0; } } public const ushort UP = 1; public const ushort DOWN = 2; public const ushort LEFT = 4; public const ushort RIGHT = 8; public const ushort START = 16; public const ushort BACK = 32; public const ushort L3 = 64; public const ushort R3 = 128; public const ushort LB = 256; public const ushort RB = 512; public const ushort A = 4096; public const ushort B = 8192; public const ushort X = 16384; public const ushort Y = 32768; private static readonly Snapshot[] _cur = new Snapshot[8]; private static readonly Snapshot[] _prev = new Snapshot[8]; private static int _frame = -1; public static int Count { get { //IL_0002: 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) try { return Gamepad.all.Count; } catch { return 0; } } } public static int DeviceIdAt(int i) { //IL_0002: 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) try { ReadOnlyArray<Gamepad> all = Gamepad.all; return (i >= 0 && i < all.Count) ? ((InputDevice)all[i]).deviceId : (-1); } catch { return -1; } } public static int IndexOfDevice(int id) { //IL_0002: 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) try { ReadOnlyArray<Gamepad> all = Gamepad.all; for (int i = 0; i < all.Count && i < 8; i++) { if (all[i] != null && ((InputDevice)all[i]).deviceId == id) { return i; } } } catch { } return -1; } public static string NameAt(int i) { //IL_0002: 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) try { ReadOnlyArray<Gamepad> all = Gamepad.all; if (i < 0 || i >= all.Count) { return "Gamepad"; } return (string.IsNullOrEmpty(((InputControl)all[i]).displayName) ? "Gamepad" : ((InputControl)all[i]).displayName) + " #" + (i + 1); } catch { return "Gamepad"; } } public static int Resolve(int idx) { int count = Count; if (count <= 0) { return 0; } return Mathf.Clamp(idx, 0, Mathf.Min(count, 8) - 1); } public static Snapshot Cur(int i) { Refresh(); return _cur[Mathf.Clamp(i, 0, 7)]; } public static Snapshot Prev(int i) { Refresh(); return _prev[Mathf.Clamp(i, 0, 7)]; } public static bool Down(int i, ushort mask) { Snapshot snapshot = Cur(i); Snapshot snapshot2 = Prev(i); return snapshot.Has(mask) && !snapshot2.Has(mask); } private static void Refresh() { if (_frame != Time.frameCount) { _frame = Time.frameCount; for (int i = 0; i < 8; i++) { _prev[i] = _cur[i]; _cur[i] = Read(i); } } } private static Snapshot Read(int i) { //IL_000a: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: 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_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) Snapshot result = default(Snapshot); try { ReadOnlyArray<Gamepad> all = Gamepad.all; if (i >= all.Count) { return result; } Gamepad val = all[i]; if (val == null) { return result; } result.Connected = true; ushort num = 0; if (val.buttonSouth.isPressed) { num |= 0x1000; } if (val.buttonEast.isPressed) { num |= 0x2000; } if (val.buttonWest.isPressed) { num |= 0x4000; } if (val.buttonNorth.isPressed) { num |= 0x8000; } if (val.leftShoulder.isPressed) { num |= 0x100; } if (val.rightShoulder.isPressed) { num |= 0x200; } if (val.leftStickButton.isPressed) { num |= 0x40; } if (val.rightStickButton.isPressed) { num |= 0x80; } if (val.startButton.isPressed) { num |= 0x10; } if (val.selectButton.isPressed) { num |= 0x20; } if (val.dpad.up.isPressed) { num |= 1; } if (val.dpad.down.isPressed) { num |= 2; } if (val.dpad.left.isPressed) { num |= 4; } if (val.dpad.right.isPressed) { num |= 8; } result.Buttons = num; Vector2 val2 = Deadzone(((InputControl<Vector2>)(object)val.leftStick).ReadValue(), 0.15f); Vector2 val3 = Deadzone(((InputControl<Vector2>)(object)val.rightStick).ReadValue(), 0.15f); result.LX = val2.x; result.LY = val2.y; result.RX = val3.x; result.RY = val3.y; result.LT = ((InputControl<float>)(object)val.leftTrigger).ReadValue(); result.RT = ((InputControl<float>)(object)val.rightTrigger).ReadValue(); } catch (Exception ex) { if (_frame % 600 == 0) { SplitScreenPlugin.Log.LogWarning((object)("Gamepad read failed: " + ex.Message)); } } return result; } private static Vector2 Deadzone(Vector2 v, float dz) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) float magnitude = ((Vector2)(ref v)).magnitude; if (magnitude < dz) { return Vector2.zero; } return v * (Mathf.Min(1f, (magnitude - dz) / (1f - dz)) / magnitude); } } internal static class InputRouter { private class HoldTrack { public float Start = -1f; public float LastPress = -1000f; public float LastDur; public int ReleaseFrame = -10; } public static int Bypass; private static readonly Dictionary<string, HoldTrack>[] _holds = new Dictionary<string, HoldTrack>[2] { new Dictionary<string, HoldTrack>(), new Dictionary<string, HoldTrack>() }; private static bool Applies() { if (!LocalPlayerManager.Joined || Bypass > 0) { return false; } return LocalPlayerManager.Depth > 0; } public static void Veto(string method, string button, ref bool result) { if (!result || button == null || Bypass > 0 || !LocalPlayerManager.Joined || LocalPlayerManager.Depth > 0 || (Object)(object)LocalPlayerManager.Players[1] == (Object)null || !SplitScreenPlugin.RouteSharedInput.Value || DevicePicker.Active || CharacterPicker.Active) { return; } int owner = MenuNav.Owner; int s = 1 - owner; if (DeviceMap.IsKbm(s)) { return; } int num = DeviceMap.PadIndex(s); if (num < 0 || !GameBindings.TryQuery(method, button, num, out var result2) || !result2) { return; } if (DeviceMap.IsKbm(owner)) { if (button.StartsWith("Joy", StringComparison.OrdinalIgnoreCase)) { result = false; } return; } int num2 = DeviceMap.PadIndex(owner); if (num2 >= 0 && GameBindings.TryQuery(method, button, num2, out var result3) && !result3) { result = false; } } private static int CurrentSlot() { return LocalPlayerManager.ActiveSlot; } private static bool Pressed(Pads.Snapshot s, string logical) { return logical.ToLowerInvariant() switch { "jump" => s.Has(4096), "dodge" => s.Has(8192), "use" => s.Has(16384), "inventory" => s.Has(32768), "attack" => s.RT > 0.5f, "secondaryattack" => s.Has(512), "block" => s.LT > 0.5f, "altplace" => s.Has(256), "run" => s.Has(64), "crouch" => s.Has(128), "map" => s.Has(32), "hotbarleft" => s.Has(4), "hotbarright" => s.Has(8), "buttona" => s.Has(4096), "buttonb" => s.Has(8192), "buttonx" => s.Has(16384), "buttony" => s.Has(32768), "lbumper" => s.Has(256), "rbumper" => s.Has(512), "ltrigger" => s.LT > 0.5f, "rtrigger" => s.RT > 0.5f, "back" => s.Has(32), "start" => s.Has(16), "lstick" => s.Has(64), "rstick" => s.Has(128), "dpadup" => s.Has(1), "dpaddown" => s.Has(2), "dpadleft" => s.Has(4), "dpadright" => s.Has(8), "lstickleft" => s.LX < -0.5f, "lstickright" => s.LX > 0.5f, "lstickup" => s.LY > 0.5f, "lstickdown" => s.LY < -0.5f, "rstickleft" => s.RX < -0.5f, "rstickright" => s.RX > 0.5f, "rstickup" => s.RY > 0.5f, "rstickdown" => s.RY < -0.5f, _ => false, }; } public static bool OverrideBool(string method, string button, ref bool result) { if (WheelMouseState.On) { if (method == "IsGamepadActive" || method == "IsExclusiveGamepadActive") { result = true; return false; } if (method == "IsMouseActive" || method == "IsGamepadMouseActive") { result = false; return false; } } if (UiInput.BlockKeyboard && button != null && !button.StartsWith("Joy", StringComparison.OrdinalIgnoreCase)) { result = false; return false; } if (!Applies()) { return true; } int num = CurrentSlot(); bool flag = DeviceMap.IsKbm(num); if (button != null && UiInput.Blocks(num)) { result = false; return false; } if (button != null && !flag && MouseUse.MouseOwnsDrag(num) && (button == "JoyButtonA" || button == "JoyButtonX" || button == "JoyButtonY")) { result = false; return false; } if (button != null && flag && MouseUse.OverOtherWindow(num) && (button == "Attack" || button == "SecondaryAttack" || button == "Block")) { result = false; return false; } if (method == "IsGamepadActive" || method == "IsExclusiveGamepadActive") { result = !flag; return false; } if (method == "IsMouseActive") { result = flag; return false; } if (method == "IsGamepadMouseActive") { result = false; return false; } if (button == null) { return true; } bool flag2 = button.StartsWith("Joy", StringComparison.OrdinalIgnoreCase); if (flag) { if (flag2) { result = false; return false; } return true; } int num2 = DeviceMap.PadIndex(num); if (num2 < 0) { result = false; return false; } if (GameBindings.TryQuery(method, button, num2, out var result2)) { result = result2; return false; } string logical = (flag2 ? button.Substring(3) : button); bool flag3 = Pressed(Pads.Cur(num2), logical); bool flag4 = Pressed(Pads.Prev(num2), logical); if (method == "GetButtonDown") { result = flag3 && !flag4; } else if (method == "GetButtonUp") { result = !flag3 && flag4; } else { result = flag3; } return false; } public static bool OverrideTimer(string method, string button, ref float result) { if (!Applies() || button == null) { return true; } int num = CurrentSlot(); bool flag = button.StartsWith("Joy", StringComparison.OrdinalIgnoreCase); if (DeviceMap.IsKbm(num)) { if (flag) { result = 0f; return false; } return true; } int num2 = DeviceMap.PadIndex(num); if (num2 < 0 || !flag) { result = 0f; return false; } if (!GameBindings.TryQuery("GetButton", button, num2, out var result2)) { result2 = false; } if (!_holds[num].TryGetValue(button, out var value)) { value = new HoldTrack(); _holds[num][button] = value; } float time = Time.time; if (result2) { if (value.Start < 0f) { value.Start = time; value.LastPress = time; } value.LastDur = time - value.Start; } else if (value.Start >= 0f) { value.Start = -1f; value.ReleaseFrame = Time.frameCount; } if (method == "GetButtonLastPressedTimer") { result = time - value.LastPress; } else { result = (result2 ? value.LastDur : ((Time.frameCount - value.ReleaseFrame <= 1) ? value.LastDur : 0f)); } return false; } public static bool OverrideFloat(string method, ref float result) { if (!Applies()) { return true; } int num = CurrentSlot(); int num2 = DeviceMap.PadIndex(num); if (DeviceMap.IsKbm(num) || num2 < 0 || UiInput.Blocks(num)) { result = 0f; return false; } Pads.Snapshot snapshot = Pads.Cur(num2); float num3 = (SplitScreenPlugin.InvertStickY.Value ? (-1f) : 1f); switch (method) { case "GetJoyLeftStickX": result = snapshot.LX; break; case "GetJoyLeftStickY": result = num3 * snapshot.LY; break; case "GetJoyRightStickX": result = snapshot.RX; break; case "GetJoyRightStickY": result = num3 * snapshot.RY; break; case "GetJoyLTrigger": result = snapshot.LT; break; case "GetJoyRTrigger": result = snapshot.RT; break; default: return true; } return false; } public static bool OverrideVector2(string method, ref Vector2 result) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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) if (WheelMouseState.On && (method == "GetJoyLeftStick" || method == "GetJoyRightStick")) { result = WheelMouseState.Stick; return false; } if (!Applies()) { return true; } int num = CurrentSlot(); int num2 = DeviceMap.PadIndex(num); if (DeviceMap.IsKbm(num) || num2 < 0 || UiInput.Blocks(num)) { result = Vector2.zero; return false; } Pads.Snapshot snapshot = Pads.Cur(num2); if (!(method == "GetJoyLeftStick")) { if (!(method == "GetJoyRightStick")) { return true; } result = new Vector2(snapshot.RX, SplitScreenPlugin.InvertLookY.Value ? (0f - snapshot.RY) : snapshot.RY); } else { result = new Vector2(snapshot.LX, snapshot.LY); } return false; } } internal static class ZInputBoolTargets { public static IEnumerable<MethodInfo> All() { foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(ZInput))) { if (m.ReturnType == typeof(bool) && !m.GetParameters().Any((ParameterInfo p) => p.ParameterType.IsByRef) && (m.Name.StartsWith("GetButton") || m.Name == "IsGamepadActive" || m.Name == "IsExclusiveGamepadActive" || m.Name == "IsMouseActive" || m.Name == "IsGamepadMouseActive")) { yield return m; } } } public static bool NamedButton(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return parameters.Length != 0 && parameters[0].ParameterType == typeof(string); } } [HarmonyPatch] internal static class ZInput_Bool { private static bool Prepare() { return TargetMethods().Any(); } private static IEnumerable<MethodBase> TargetMethods() { return ZInputBoolTargets.All().Where(ZInputBoolTargets.NamedButton).Cast<MethodBase>(); } private static bool Prefix(MethodBase __originalMethod, string __0, ref bool __result) { return InputRouter.OverrideBool(__originalMethod.Name, __0, ref __result); } private static void Postfix(MethodBase __originalMethod, string __0, ref bool __result) { InputRouter.Veto(__originalMethod.Name, __0, ref __result); } } [HarmonyPatch] internal static class ZInput_BoolOther { private static bool Prepare() { return TargetMethods().Any(); } private static IEnumerable<MethodBase> TargetMethods() { return (from m in ZInputBoolTargets.All() where !ZInputBoolTargets.NamedButton(m) select m).Cast<MethodBase>(); } private static bool Prefix(MethodBase __originalMethod, ref bool __result) { return InputRouter.OverrideBool(__originalMethod.Name, null, ref __result); } } [HarmonyPatch] internal static class ZInput_Timers { private static bool Prepare() { return TargetMethods().Any(); } private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(ZInput))) { ParameterInfo[] ps = m.GetParameters(); if (m.ReturnType == typeof(float) && m.Name.StartsWith("GetButton") && m.Name.EndsWith("Timer") && ps.Length >= 1 && ps[0].ParameterType == typeof(string)) { yield return m; } } } private static bool Prefix(MethodBase __originalMethod, string __0, ref float __result) { return InputRouter.OverrideTimer(__originalMethod.Name, __0, ref __result); } } [HarmonyPatch] internal static class ZInput_Float { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(ZInput))) { if (m.ReturnType == typeof(float) && m.Name.StartsWith("GetJoy")) { yield return m; } } } private static bool Prefix(MethodBase __originalMethod, ref float __result) { return InputRouter.OverrideFloat(__originalMethod.Name, ref __result); } } [HarmonyPatch] internal static class ZInput_Stick { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(ZInput))) { if (m.ReturnType == typeof(Vector2) && (m.Name == "GetJoyLeftStick" || m.Name == "GetJoyRightStick")) { yield return m; } } } private static bool Prefix(MethodBase __originalMethod, ref Vector2 __result) { return InputRouter.OverrideVector2(__originalMethod.Name, ref __result); } } [HarmonyPatch] internal static class ZInput_MouseDelta { private static IEnumerable<MethodBase> TargetMethods() { foreach (MethodInfo m in AccessTools.GetDeclaredMethods(typeof(ZInput))) { if (m.ReturnType == typeof(Vector2) && m.Name == "GetMouseDelta") { yield return m; } } } private static bool Prefix(ref Vector2 __result) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (UiInput.BlockKeyboard || WheelMouseState.On || (LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && (!DeviceMap.IsKbm(LocalPlayerManager.ActiveSlot) || UiInput.Blocks(LocalPlayerManager.ActiveSlot)))) { __result = Vector2.zero; return false; } return true; } } internal static class Refl { private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary<string, FieldInfo> _fields = new Dictionary<string, FieldInfo>(); public static FieldInfo Field(Type t, string name) { if (t == null || string.IsNullOrEmpty(name)) { return null; } string key = t.AssemblyQualifiedName + "|" + name; if (_fields.TryGetValue(key, out var value)) { return value; } Type type = t; while (type != null && value == null) { try { value = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { } type = type.BaseType; } _fields[key] = value; return value; } public static FieldInfo FieldOrType(Type t, string name, Type want) { FieldInfo value = Field(t, name); if (value != null || t == null || want == null) { return value; } string key = t.AssemblyQualifiedName + "|type:" + want.FullName; if (_fields.TryGetValue(key, out value)) { return value; } Type type = t; while (type != null && value == null) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (want.IsAssignableFrom(fieldInfo.FieldType)) { value = fieldInfo; break; } } type = type.BaseType; } _fields[key] = value; return value; } public static MethodInfo DeclaredMethod(Type t, string name, Type[] args = null) { if (t == null) { return null; } try { if (args != null) { return t.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, args, null); } MethodInfo[] methods = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == name) { return methodInfo; } } } catch { } return null; } public static MethodInfo Method(Type t, string name, Type[] args = null) { Type type = t; while (type != null) { MethodInfo methodInfo = DeclaredMethod(type, name, args); if (methodInfo != null) { return methodInfo; } type = type.BaseType; } return null; } public static GameObject GoOf(object el) { if (el == null) { return null; } GameObject val = (GameObject)((el is GameObject) ? el : null); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((el is Component) ? el : null); if ((Object)(object)val2 != (Object)null) { return val2.gameObject; } FieldInfo fieldInfo = FieldOrType(el.GetType(), "m_go", typeof(GameObject)); if (fieldInfo != null) { object? value = fieldInfo.GetValue(el); return (GameObject)((value is GameObject) ? value : null); } fieldInfo = FieldOrType(el.GetType(), "m_go", typeof(RectTransform)) ?? FieldOrType(el.GetType(), "m_go", typeof(Component)); Component val3 = (Component)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); return ((Object)(object)val3 != (Object)null) ? val3.gameObject : null; } } internal static class LocalPlayerManager { private struct Ctx { public Player Player; public int Slot; public bool PoseSwapped; public Vector3 Pos; public Quaternion Rot; public bool InvSwapped; public InventoryGui Inv; public bool EhSwapped; public Component Eh; public bool GrassSwapped; public Component Grass; public object[] RadialPrev; public bool RefSaved; public Vector3 Ref; } public const int MaxLocal = 2; public static readonly Player[] Players = (Player[])(object)new Player[2]; public static readonly PlayerController[] Controllers = (PlayerController[])(object)new PlayerController[2]; public static bool Joined; public static int InventoryOwner; public static float RespawnAt; private static readonly FieldInfo _refPos = Refl.Field(typeof(ZNet), "m_referencePosition"); private static readonly Stack<Ctx> _stack = new Stack<Ctx>(); public static int SkipInventoryGuiFrame = -1; private static bool _spawnedOnce; private static bool _deathSaved; internal static readonly MethodInfo TeleportToMethod = Refl.Method(typeof(Player), "TeleportTo", new Type[3] { typeof(Vector3), typeof(Quaternion), typeof(bool) }); private static bool _p1Travelling; public static int ActiveSlot { get; private set; } public static int Depth => _stack.Count; public static void Enter(int slot) { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) Ctx item = new Ctx { Player = Player.m_localPlayer, Slot = ActiveSlot }; if ((Object)(object)Players[slot] != (Object)null) { Player.m_localPlayer = Players[slot]; } if (InvClone.Active) { item.InvSwapped = true; item.Inv = InventoryGui.instance; InvClone.SetInstance((slot == 1) ? InvClone.Gui2 : InvClone.Gui1); } UiCopy ui = NameplateCopy.Ui; if (ui.Active) { item.EhSwapped = true; item.Eh = ui.GetInstance(); ui.SetInstance((slot == 1) ? ui.Copy : ui.Orig); } if (GrassCopy.Active) { item.GrassSwapped = true; item.Grass = GrassCopy.GetInstance(); GrassCopy.SetInstance((slot == 1) ? GrassCopy.Copy : GrassCopy.Orig); } if (RadialCopy.Active) { item.RadialPrev = RadialCopy.SwapTo(slot == 1); } if (slot == 1 && (Object)(object)SecondaryCamera.Instance != (Object)null && (Object)(object)GameCamera.instance != (Object)null) { Transform transform = ((Component)GameCamera.instance).transform; item.PoseSwapped = true; item.Pos = transform.position; item.Rot = transform.rotation; transform.SetPositionAndRotation(((Component)SecondaryCamera.Instance).transform.position, ((Component)SecondaryCamera.Instance).transform.rotation); } if (slot == 1 && ActiveSlot != 1 && _refPos != null && (Object)(object)ZNet.instance != (Object)null) { try { item.Ref = (Vector3)_refPos.GetValue(ZNet.instance); item.RefSaved = true; } catch { } } ActiveSlot = slot; _stack.Push(item); } public static void Exit() { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if (_stack.Count == 0) { return; } Ctx ctx = _stack.Pop(); Player.m_localPlayer = (((Object)(object)ctx.Player != (Object)null) ? ctx.Player : null); if (ctx.InvSwapped) { InvClone.SetInstance(ctx.Inv); } if (ctx.EhSwapped) { NameplateCopy.Ui.SetInstance(ctx.Eh); } if (ctx.GrassSwapped) { GrassCopy.SetInstance(ctx.Grass); } if (ctx.RadialPrev != null) { RadialCopy.Restore(ctx.RadialPrev); } if (ctx.PoseSwapped && (Object)(object)GameCamera.instance != (Object)null) { ((Component)GameCamera.instance).transform.SetPositionAndRotation(ctx.Pos, ctx.Rot); } if (ctx.RefSaved && (Object)(object)ZNet.instance != (Object)null) { try { _refPos.SetValue(ZNet.instance, ctx.Ref); } catch { } } ActiveSlot = ctx.Slot; } public static bool EnterFor(object instance) { if (!Joined || (Object)(object)Players[1] == (Object)null) { return false; } int num = SlotFor(instance); if (num < 0) { return false; } Enter(num); return true; } private static int SlotFor(object inst) { Player val = (Player)((inst is Player) ? inst : null); if ((Object)(object)val != (Object)null) { return ((Object)(object)val == (Object)(object)Players[1]) ? 1 : ((!((Object)(object)val == (Object)(object)Players[0])) ? (-1) : 0); } PlayerController val2 = (PlayerController)((inst is PlayerController) ? inst : null); if ((Object)(object)val2 != (Object)null) { return ((Object)(object)val2 == (Object)(object)Controllers[1]) ? 1 : ((!((Object)(object)val2 == (Object)(object)Controllers[0])) ? (-1) : 0); } InventoryGui val3 = (InventoryGui)((inst is InventoryGui) ? inst : null); if ((Object)(object)val3 != (Object)null) { return (!InvClone.Active) ? InventoryOwner : (((Object)(object)val3 == (Object)(object)InvClone.Gui2) ? 1 : 0); } return -1; } public static void HandleInventoryButtons() { bool flag = InventoryGui.IsVisible(); bool flag2 = InventoryOpenPressedBy(0); bool flag3 = InventoryOpenPressedBy(1); bool flag4 = false; if (flag2 && Backpack.Open[0]) { Backpack.Close(0); flag2 = false; flag4 = true; } if (flag3 && Backpack.Open[1]) { Backpack.Close(1); flag3 = false; flag4 = true; } if (flag) { if (flag2 && InventoryOwner != 0) { Backpack.OpenFor(0); flag4 = true; } if (flag3 && InventoryOwner != 1) { Backpack.OpenFor(1); flag4 = true; } } else if (flag2 && flag3) { Backpack.OpenFor(1); InventoryOwner = 0; } else { InventoryOwner = (flag3 ? 1 : 0); } if (flag4) { SkipInventoryGuiFrame = Time.frameCount; } } private static bool InventoryOpenPressedBy(int slot) { if (DeviceMap.IsKbm(slot)) { if (_stack.Count != 0) { return false; } InputRouter.Bypass++; try { return ZInput.GetButtonDown("Inventory"); } catch { return false; } finally { InputRouter.Bypass--; } } int num = DeviceMap.PadIndex(slot); if (num < 0) { return false; } if (GameBindings.TryQuery("GetButtonDown", "JoyInventory", num, out var result) && result) { return true; } return Pads.Down(num, 32768); } public static void TrackPrimary() { if (_stack.Count == 0) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer != (Object)(object)Players[1]) { Players[0] = localPlayer; Controllers[0] = ((Component)localPlayer).GetComponent<PlayerController>(); } } } public static void Join(Player p1) { Joined = true; RespawnAt = 0f; _spawnedOnce = false; CharacterSlot.OnJoin(); SecondaryCamera.Create(); SpawnSecondary(p1); SplitLayout.ApplyAll(); SetupUi.BannerUntil = Time.unscaledTime + 7f; SplitScreenPlugin.Log.LogInfo((object)("Player 2 joined. P1=" + DeviceMap.Label(0) + " P2=" + DeviceMap.Label(1))); } public static void Leave() { CharacterSlot.SaveP2(); P2Build.Reset(); if ((Object)(object)Players[1] != (Object)null) { Costume.Clear(Players[1]); } AppearanceUi.CloseAll(); NameEntry.Close(cancelled: false); WorldPriority.Restore(); SplitLayout.Reset(); if ((Object)(object)Players[1] != (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)Players[1]).gameObject); } Players[1] = null; Controllers[1] = null; SecondaryCamera.Destroy(); Joined = false; InventoryOwner = 0; RespawnAt = 0f; _stack.Clear(); ActiveSlot = 0; Backpack.CloseAll(); SplitScreenPlugin.Log.LogInfo((object)"Player 2 left."); } public static void SpawnSecondary(Player p1) { //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_001a: 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) GameObject playerPrefab = Game.instance.m_playerPrefab; Vector3 val = Rescue.LandingSpot(p1); Player localPlayer = Player.m_localPlayer; GameObject val2 = Object.Instantiate<GameObject>(playerPrefab, val, ((Component)p1).transform.rotation); Player.m_localPlayer = localPlayer; Player component = val2.GetComponent<Player>(); Players[1] = component; Controllers[1] = val2.GetComponent<PlayerController>(); RespawnAt = 0f; try { ZNetView component2 = val2.GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid()) { component2.GetZDO().Set("playerName", "Player 2"); } } catch (Exception ex) { SplitScreenPlugin.Log.LogWarning((object)("Could not name P2: " + ex.Message)); } if ((Object)(object)SecondaryCamera.Instance != (Object)null) { SecondaryCamera.Instance.Target = component; } RadialCopy.FixPlayer(component); CharacterSlot.ApplyOnSpawn(component, _spawnedOnce); _spawnedOnce = true; _deathSaved = false; } public static void Tick(Player p1) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) Player val = Players[1]; if ((Object)(object)val == (Object)null) { if (Time.time >= RespawnAt && !((Character)p1).IsDead() && !((Character)p1).IsTeleporting()) { SpawnSecondary(p1); } } else if (((Character)val).IsDead()) { if (!_deathSaved) { _deathSaved = true; CharacterSlot.SaveP2(); } if (RespawnAt <= 0f) { RespawnAt = Time.time + SplitScreenPlugin.RespawnDelay.Value; } if (Time.time >= RespawnAt) { ZNetScene.instance.Destroy(((Component)val).gameObject); Players[1] = null; } } else if (((Character)p1).IsTeleporting() || ((Character)p1).IsDead()) { if (((Character)p1).IsTeleporting()) { _p1Travelling = true; } } else if (_p1Travelling) { _p1Travelling = false; if (Vector3.Distance(((Component)p1).transform.position, ((Component)val).transform.position) > 15f) { Rescue.PullToP1("followed Player 1 through a portal"); } } else { if (((Character)val).IsTeleporting()) { return; } float value = SplitScreenPlugin.LeashDistance.Value; if (value > 0f) { Vector3 val2 = ((Component)val).transform.position - ((Component)p1).transform.position; if (((Vector3)(ref val2)).sqrMagnitude > value * value) { Rescue.PullToP1("tether " + value.ToString("F0") + " m"); } } } } } [HarmonyPatch] internal static class ContextPatches { private static IEnumerable<MethodBase> TargetMethods() { List<KeyValuePair<Type, string>> wanted = new List<KeyValuePair<Type, string>> { new KeyValuePair<Type, string>(typeof(Player), "Update"), new KeyValuePair<Type, string>(typeof(Player), "FixedUpdate"), new KeyValuePair<Type, string>(typeof(Player), "LateUpdate"), new KeyValuePair<Type, string>(typeof(Player), "OnDeath"), new KeyValuePair<Type, string>(typeof(PlayerController), "FixedUpdate"), new KeyValuePair<Type, string>(typeof(PlayerController), "LateUpdate") }; foreach (KeyValuePair<Type, string> kv in wanted) { MethodInfo m = Refl.DeclaredMethod(kv.Key, kv.Value); if (m != null) { yield return m; } else { SplitScreenPlugin.Log.LogWarning((object)("Not found (skipped): " + kv.Key.Name + "." + kv.Value)); } } } private static bool Prefix(object __instance, out bool __state) { __state = LocalPlayerManager.EnterFor(__instance); return true; } private static Exception Finalizer(Exception __exception, bool __state) { if (__state) { LocalPlayerManager.Exit(); } return __exception; } } [HarmonyPatch(typeof(PlayerController), "TakeInput")] internal static class TakeInputPatch { private static bool Prefix(ref bool __result) { if (DevicePicker.Active || CharacterPicker.Active) { __result = false; return false; } if (LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && UiInput.Blocks(LocalPlayerManager.ActiveSlot)) { __result = false; return false; } if (LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && Backpack.Open[LocalPlayerManager.ActiveSlot]) { __result = false; return false; } if (!LocalPlayerManager.Joined || LocalPlayerManager.Depth == 0 || LocalPlayerManager.ActiveSlot != 1) { return true; } Player val = LocalPlayerManager.Players[1]; bool flag = (InvClone.Active ? InventoryGui.IsVisible() : (InventoryGui.IsVisible() && LocalPlayerManager.InventoryOwner == 1)); bool flag2 = (RadialCopy.Active ? RadialCopy.CopyOpen() : (RadialState.Open() && RadialState.Owner == 1)); __result = (Object)(object)val != (Object)null && !((Character)val).IsDead() && !flag && !flag2; return false; } private static void Postfix(ref bool __result) { if (!__result && LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && LocalPlayerManager.ActiveSlot == 0 && !DevicePicker.Active && !CharacterPicker.Active && !Backpack.Open[0] && !RadialCopy.Active && RadialState.Open() && RadialState.Owner == 1 && !Menu.IsVisible() && !Minimap.IsOpen() && !InvClone.IsVisibleSafe(0)) { Player val = LocalPlayerManager.Players[0]; if ((Object)(object)val != (Object)null && !((Character)val).IsDead()) { __result = true; return; } } if (!__result && !DevicePicker.Active && LocalPlayerManager.Joined && LocalPlayerManager.Depth != 0 && LocalPlayerManager.ActiveSlot == 0 && !Backpack.Open[0] && !InvClone.Active && InventoryGui.IsVisible() && LocalPlayerManager.InventoryOwner == 1 && !Menu.IsVisible() && !Minimap.IsOpen()) { Player val2 = LocalPlayerManager.Players[0]; if ((Object)(object)val2 != (Object)null && !((Character)val2).IsDead()) { __result = true; } } } } [HarmonyPatch(typeof(PlayerController), "InInventoryEtc")] internal static class InInventoryEtcPatch { private static void Postfix(ref bool __result) { if (!InvClone.Active && __result && LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && InventoryGui.IsVisible() && LocalPlayerManager.InventoryOwner != LocalPlayerManager.ActiveSlot && !Menu.IsVisible() && !Minimap.IsOpen()) { __result = false; } } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class MouseCapturePatch { private static void Postfix() { if (CharacterPicker.Active || NameEntry.Active) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { if (!LocalPlayerManager.Joined) { return; } if (UiInput.KbmSlot >= 0 && VMenus.AnyFor(UiInput.KbmSlot)) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return; } int num = ((!DeviceMap.IsKbm(0)) ? (DeviceMap.IsKbm(1) ? 1 : (-1)) : 0); if (num >= 0 && Backpack.Open[num]) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return; } Keyboard current = Keyboard.current; if (current != null && (((ButtonControl)current.leftAltKey).isPressed || ((ButtonControl)current.rightAltKey).isPressed) && !Menu.IsVisible()) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else if (InvClone.Active) { if (num < 0 && MouseUse.HelpAllowed && InvClone.IsVisible(InvClone.Gui2) && !Menu.IsVisible()) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else if (num == 1) { if (InvClone.IsVisible(InvClone.Gui2)) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else if (!Menu.IsVisible() && !Minimap.IsOpen()) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } } else if (InventoryGui.IsVisible() && !DeviceMap.IsKbm(LocalPlayerManager.InventoryOwner) && !Menu.IsVisible() && !Minimap.IsOpen()) { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } } } [HarmonyPatch(typeof(Game), "RequestRespawn")] internal static class RequestRespawnPatch { private static bool Prefix() { if (LocalPlayerManager.Joined && LocalPlayerManager.ActiveSlot == 1) { LocalPlayerManager.RespawnAt = Time.time + SplitScreenPlugin.RespawnDelay.Value; return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "Show")] internal static class InventoryShowPatch { private static void Postfix() { if (LocalPlayerManager.Joined && LocalPlayerManager.Depth > 0 && !InvClone.Active) { LocalPlayerManager.InventoryOwner = LocalPlayerManager.ActiveSlot; } } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryHidePatch { private static void Postfix() { if (LocalPlayerManager.Joined) { LocalPlayerManager.InventoryOwner = 0; } } } internal class SecondaryCamera : MonoBehaviour { public static SecondaryCamera Instance; public Camera Cam; public Player Target; public static void Create() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown Destroy(); Camera mainCam = SplitLayout.MainCam; if ((Object)(object)mainCam == (Object)null) { SplitScreenPlugin.Log.LogError((object)"No main camera."); return; } GameObject val = new GameObject("SplitScreen_P2_Camera"); val.SetActive(false); Camera val2 = val.AddComponent<Camera>(); val2.CopyFrom(mainCam); val2.targetTexture = null; val2.ResetAspect(); CopyPostProcessing(mainCam, val); SecondaryCamera secondaryCamera = val.AddComponent<SecondaryCamera>(); secondaryCamera.Cam = val2; Instance = secondaryCamera; val.SetActive(true); } public static void Destroy() { if ((Object)(object)Instance != (Object)null) { Object.Destroy((Object)(object)((Component)Instance).gameObject); } Instance = null; } private static void CopyPostProcessing(Camera src, GameObject dst) { Behaviour[] components = ((Component)src).GetComponents<Behaviour>(); foreach (Behaviour val in components) { Type type = ((object)val).GetType(); string text = type.Namespace ?? ""; if (!text.StartsWith("UnityEngine.PostProcessing") && !text.StartsWith("UnityEngine.Rendering.PostProcessing")) { continue; } try { Component val2 = dst.AddComponent(type); CopySerializedFields((Component)(object)val, val2); FieldInfo field = type.GetField("volumeTrigger"); if (field != null && field.FieldType == typeof(Transform)) { field.SetValue(val2, dst.transform); } } catch (Exception ex) { SplitScreenPlugin.Log.LogWarning((object)("PostFX copy failed for " + type.Name + ": " + ex.Message)); } } } internal static void CopySerializedFields(Component from, Component to) { Type type = ((object)from).GetType(); while (type != null && type != typeof(Behaviour) && type != typeof(Component)) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.IsInitOnly || fieldInfo.IsLiteral || fieldInfo.IsNotSerialized || (!fieldInfo.IsPublic && fieldInfo.GetCustomAttributes(typeof(SerializeField), inherit: true).Length == 0)) { continue; } try { object obj = fieldInfo.GetValue(from); ScriptableObject val = (ScriptableObject)((obj is ScriptableObject) ? obj : null); if ((Object)(object)val != (Object)null && fieldInfo.Name.IndexOf("profile", StringComparison.OrdinalIgnoreCase) >= 0) { obj = Object.Instantiate<ScriptableObject>(val); } fieldInfo.SetValue(to, obj); } catch { } } type = type.BaseType; } } private void LateUpdate() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00a4: 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_0087: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null)) { Vector3 lookDir = ((Character)Target).GetLookDir(); Vector3 eyePoint = ((Character)Target).GetEyePoint(); float value = SplitScreenPlugin.CameraDistance.Value; Vector3 val = eyePoint - lookDir * value + Vector3.up * 0.3f; Vector3 val2 = val - eyePoint; RaycastHit val3 = default(RaycastHit); if (Physics.Raycast(eyePoint, ((Vector3)(ref val2)).normalized, ref val3, value, -1, (QueryTriggerInteraction)1)) { val = ((RaycastHit)(ref val3)).point + ((RaycastHit)(ref val3)).normal * 0.2f; } ((Component)this).transform.SetPositionAndRotation(val, Quaternion.LookRotation(lookDir)); } } } internal static class SplitLayout { public static bool Active; public static RenderTexture Rt1; private static Camera _main; private static int _w; private static int _h; private static bool _useGameFb; private static RawImage _gameRaw; private static bool _nativeMode; private static GameObject _viewsGo; private static RawImage _p1Raw; private static RawImage _p2Raw; private static Material _blitMat; private static int _invSlotApplied = -1; public static readonly HalfWrap HudWrap = new HalfWrap(); public static readonly HalfWrap InvWrap = new HalfWrap(); public static readonly HalfWrap InvWrap2 = new HalfWrap(); public static int UiLayer => LayerMask.NameToLayer("UI"); public static Camera MainCam { get { if ((Object)(object)_main == (Object)null && (Object)(object)GameCamera.instance != (Object)null) { _main = ((Component)GameCamera.instance).GetComponent<Camera>(); } return _main; } } public static string Describe() { Texture val = P1Source(); return (_useGameFb ? "GameFB" : "ScreenRect") + " P1src=" + (((Object)(object)val != (Object)null) ? (((Object)val).name + " " + val.width + "x" + val.height) : "none") + " P2rt=" + (((Object)(object)Rt1 != (Object)null) ? (((Texture)Rt1).width + "x" + ((Texture)Rt1).height) : "none") + " P1aspect=" + (((Object)(object)MainCam != (Object)null) ? MainCam.aspect.ToString("F2") : "?") + " HudMirror=" + HudMirror.Active + " InvOwner=P" + (LocalPlayerManager.InventoryOwner + 1); } public static Rect HalfFor(int slot) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (SplitScreenPlugin.Mode.Value == SplitMode.SideBySide) { return (slot == 0) ? new Rect(0f, 0f, 0.5f, 1f) : new Rect(0.5f, 0f, 0.5f, 1f); } return (slot == 0) ? new Rect(0f, 0.5f, 1f, 0.5f) : new Rect(0f, 0f, 1f, 0.5f); } public static Rect ViewportFor(int slot) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0054: 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_0074: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return new Rect(0f, 0f, 1f, 1f); } if (SplitScreenPlugin.Mode.Value == SplitMode.SideBySide) { return (slot == 0) ? new Rect(0f, 0f, 0.5f, 1f) : new Rect(0.5f, 0f, 0.5f, 1f); } return (slot == 0) ? new Rect(0f, 0.5f, 1f, 0.5f) : new Rect(0f, 0f, 1f, 0.5f); } public static void ApplyAll() { Active = true; Rebuild(); } private static void Rebuild() { _w = Screen.width; _h = Screen.height; Teardown(); Active = true; FindGameViewport(); Camera mainCam = MainCam; _useGameFb = SplitScreenPlugin.Frame.Value == FrameMode.GameFramebuffer && (Object)(object)mainCam != (Object)null && ((Object)(object)_gameRaw != (Object)null || (Object)(object)mainCam.targetTexture != (Object)null); if (SplitScreenPlugin.Frame.Value == FrameMode.GameFramebuffer && !_useGameFb) { SplitScreenPlugin.Log.LogWarning((object)"Game framebuffer not found; falling back to ScreenRect mode."); } if (_useGameFb) { BuildViews(); } else { ApplyCameraRects(); } if ((SplitScreenPlugin.Player2Hud.Value != P2HudMode.Mirror || !HudMirror.Start()) && SplitScreenPlugin.P1Hud.Value == HudMode.FitToViewport) { FitHud(); } if (SplitScreenPlugin.SeparateInventories.Value) { InvClone.Create(); } if (SplitScreenPlugin.PerPlayerNameplates.Value) { NameplateCopy.Create(); } RadialCopy.Create(); if (!RadialCopy.Active) { RadialState.Scan(); } WrapInventory(); if (InvClone.Active) { UiContext.Setup(InvClone.Gui1, InvClone.Gui2); } try { BuildUiContext.Setup(); } catch (Exception ex) { SplitScreenPlugin.Log.LogWarning((object)("Build UI routing failed: " + ex.Message)); } Reassert(); } public static void Tick() { if (Active && (Screen.width != _w || Screen.height != _h)) { Rebuild(); } } public static void Reset() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) Teardown(); Active = false; Camera mainCam = MainCam; if ((Object)(object)mainCam != (Object)null) { mainCam.ResetAspect(); mainCam.rect = new Rect(0f, 0f, 1f, 1f); } } private static void Teardown() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) RadialState.Clear(); HudMirror.Stop(); DragPanels.RemoveAll(); HudWrap.Unwrap(); InvWrap.Unwrap(); InvWrap2.Unwrap(); MouseUse.Reset(); MenuNav.Reset(); UiContext.Clear(); BuildUiContext.Clear(); InvClone.Destroy(); NameplateCopy.Ui.Destroy(); GrassCopy.Destroy(); RadialCopy.Destroy(); _invSlotApplied = -1; Camera val = (((Object)(object)SecondaryCamera.Instance != (Object)null) ? SecondaryCamera.Instance.Cam : null); if ((Object)(object)val != (Object)null) { val.targetTexture = null; val.rect = new Rect(0f, 0f, 1f, 1f); } if ((Object)(object)_viewsGo != (Object)null) { Object.Destroy((Object)(object)_viewsGo); } _viewsGo = null; _p1Raw = null; _p2Raw = null; if ((Object)(object)Rt1 != (Object)null) { Rt1.Release(); Object.Destroy((Object)(object)Rt1); Rt1 = null; } Camera mainCam = MainCam; if ((Object)(object)mainCam != (Object)null) { mainCam.ResetAspect(); mainCam.rect = new Rect(0f, 0f, 1f, 1f); } _gameRaw = null; _useGameFb = false; _nativeMode = false; } private static void FindGameViewport() { _gameRaw = null; Canvas[] array = Object.FindObjectsByType<Canvas>((FindObjectsSortMode)0); foreach (Canvas val in array) { if (!val.isRootCanvas || ((Object)((Component)val).gameObject).name != "Scaled 3D Viewport") { continue; } RawImage[] componentsInChildren = ((Component)val).GetComponentsInChildren<RawImage>(true); foreach (RawImage val2 in componentsInChildren) { SplitScreenPlugin.Log.LogInfo((object)("Game viewport RawImage '" + ((Object)val2).name + "' active=" + ((Behaviour)val2).isActiveAndEnabled + " tex=" + (((Object)(object)val2.texture != (Object)null) ? (((Object)val2.texture).name + " " + val2.texture.width + "x" + val2.texture.height) : "none"))); if ((Object)(object)_gameRaw == (Object)null || (!((Behaviour)_gameRaw).isActiveAndEnabled && ((Behaviour)val2).isActiveAndEnabled)) { _gameRaw = val2; } } } } private static Texture P1Source() { if ((Object)(object)_gameRaw != (Object)null && (Object)(object)_gameRaw.texture != (Object)null) { return _gameRaw.texture; } Camera mainCam = MainCam; return (Texture)(object)(((Object)(object)mainCam != (Object)null) ? mainCam.targetTexture : null); } private static RawImage MakeRaw(Transform parent, string name, Rect vp, Texture tex) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.layer = UiLayer; val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = ((Rect)(ref vp)).min; component.anchorMax = ((Rect)(ref vp)).max; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; RawImage val2 = val.AddComponent<RawImage>(); val2.texture = tex; ((Graphic)val2).raycastTarget = false; if ((Object)(object)_blitMat != (Object)null) { ((Graphic)val2).material = _blitMat; } return val2; } private static void BuildViews() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown //IL_00d1: 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_0143: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown Camera val = (((Object)(object)SecondaryCamera.Instance != (Object)null) ? SecondaryCamera.Instance.Cam : null); if ((Object)(object)val == (Object)null) { SplitScreenPlugin.Log.LogError((object)"P2 camera missing."); return; } Rect vp = ViewportFor(1); int num = Mathf.Max(16, Mathf.RoundToInt((float)Screen.width * ((Rect)(ref vp)).width)); int num2 = Mathf.Max(16, Mathf.RoundToInt((float)Screen.height * ((Rect)(ref vp)).height)); Rt1 = new RenderTexture(num, num2, 24, (RenderTextureFormat)0); ((Object)Rt1).name = "SplitScreen_P2_RT"; Rt1.antiAliasing = Mathf.Max(1, QualitySettings.antiAliasing); Rt1.Create(); val.rect = new Rect(0f, 0f, 1f, 1f); val.targetTexture = Rt1; if ((Object)(object)_blitMat == (Object)null) { Shader val2 = Shader.Find("Hidden/BlitCopy"); if ((Object)(object)val2 != (Object)null) { _blitMat = new Material(val2); } } _viewsGo = new GameObject("SplitScreen_Views", new Type[1] { typeof(RectTransform) }); _viewsGo.layer = UiLayer; Canvas val3 = _viewsGo.AddComponent<Canvas>(); val3.renderMode = (RenderMode)0; val3.sortingOrder = 50; _p1Raw = MakeRaw(_viewsGo.transform, "P1View", ViewportFor(0), P1Source()); _p2Raw = MakeRaw(_viewsGo.transform, "P2View", vp, (Texture)(object)Rt1); } public static void Reassert() { //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_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return; } Camera mainCam = MainCam; if ((Object)(object)mainCam == (Object)null) { return; } if (_useGameFb) { Rect val = ViewportFor(0); Texture val2 = P1Source(); if ((Object)(object)val2 != (Object)null) { if (_nativeMode) { _nativeMode = false; SplitScreenPlugin.Log.LogInfo((object)"Rendering: scaled - Player 1 shown from the game's picture."); } float num = (float)Screen.width * ((Rect)(ref val)).width / Mathf.Max(1f, (float)Screen.height * ((Rect)(ref val)).height); if (!Mathf.Approximately(mainCam.aspect, num)) { mainCam.aspect = num; } if (mainCam.rect != new Rect(0f, 0f, 1f, 1f)) { mainCam.rect = new Rect(0f, 0f, 1f, 1f); } if ((Object)(object)_p1Raw != (Object)null) { if (!((Behaviour)_p1Raw).enabled) { ((Behaviour)_p1Raw).enabled = true; } if ((Object)(object)_p1Raw.texture != (Object)(object)val2) { _p1Raw.texture = val2; } if ((Object)(object)_gameRaw != (Object)null) { _p1Raw.uvRect = _gameRaw.uvRect; } } } else { if (!_nativeMode) { _nativeMode = true; mainCam.ResetAspect(); SplitScreenPlugin.Log.LogInfo((object)"Rendering: native - Player 1's camera draws straight into its half."); } if (mainCam.rect != val) { mainCam.rect = val; } if ((Object)(object)_p1Raw != (Object)null && ((Behaviour)_p1Raw).enabled) { ((Behaviour)_p1Raw).enabled = false; } } } else { ApplyCameraRects(); } RadialState.Reassert(); int inventoryOwner = LocalPlayerManager.InventoryOwner; if (InvWrap.Wrapped && !InvClone.Active && inventoryOwner != _invSlotApplied) { InvWrap.SetViewport(ViewportFor(inventoryOwner)); _invSlotApplied = inventoryOwner; } } public static void ApplyCameraRects() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)MainCam != (Object)null) { MainCam.rect = ViewportFor(0); } if ((Object)(object)SecondaryCamera.Instance != (Object)null) { SecondaryCamera.Instance.Cam.rect = ViewportFor(1); } } private static void FitHud() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null) { SplitScreenPlugin.Log.LogWarning((object)"Hud.instance is null; P1 HUD left as is."); return; } HalfWrap hudWrap = HudWrap; Transform transform = ((Component)instance).transform; hudWrap.Wrap((RectTransform)(object)((transform is RectTransform) ? transform : null), ViewportFor(0), 1f); } private static void WrapInventory() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { SplitScreenPlugin.Log.LogWarning((object)"InventoryGui.instance is null; inventory left full-screen."); return; } Canvas componentInParent = ((Component)instance).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null) { SplitScreenPlugin.Log.LogWarning((object)"No Canvas above InventoryGui; inventory left full-screen."); return; } componentInParent = componentInParent.rootCanvas; float scale = Mathf.Clamp(SplitScreenPlugin.InventoryScale.Value, 0.3f, 1f); int num = ((!InvClone.Active) ? LocalPlayerManager.InventoryOwner : 0); HalfWrap invWrap = InvWrap; Transform transform = ((Component)componentInParent).transform; invWrap.Wrap((RectTransform)(object)((transform is RectTransform) ? transform : null), ViewportFor(num), scale); _invSlotApplied = num; SplitScreenPlugin.Log.LogInfo((object)("Inventory canvas '" + ((Object)componentInParent).name + "' wrapped.")); DragPanels.Attach(instance); if (InvClone.Active) { Canvas componentInParent2 = ((Component)InvClone.Gui2).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent2 != (Object)null) { HalfWrap invWrap2 = InvWrap2; Transform transform2 = ((Component)componentInParent2.rootCanvas).transform; invWrap2.Wrap((RectTransform)(object)((transform2 is RectTransform) ? transform2 : null), ViewportFor(1), scale); DragPanels.Attach(InvClone.Gui2); } } } } internal class HalfWrap { private RectTransform _root; private RectTransform _wrap; private readonly List<Transform> _kids = new List<Transform>(); public bool Wrapped => (Object)(object)_wrap != (Object)null; public RectTransform Wrapper => _wrap; public void Wrap(RectTransform root, Rect vp, float scale) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0072: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown Unwrap(); if ((Object)(object)root == (Object)null) { return; } GameObject val = new GameObject("SplitScreen_Wrapper", new Type[1] { typeof(RectTransform) }); val.layer = ((Component)root).gameObject.layer; _wrap = val.GetComponent<RectTransform>(); ((Transform)_wrap).SetParent((Transform)(object)root, false); _wrap.pivot = new Vector2(0.5f, 0.5f); ((Transform)_wrap).localScale = new Vector3(scale, scale, 1f); SetViewport(vp); _root = root; _kids.Clear(); foreach (Transform item in (Transform)root) { Transform val2 = item; if ((Object)(object)val2 != (Object)(object)_wrap) { _kids.Add(val2); } } foreach (Transform kid in _kids) { kid.SetParent((Transform)(object)_wrap, false); } } public void SetViewport(Rect vp) { //IL_001b: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_wrap == (Object)null)) { _wrap.anchorMin = ((Rect)(ref vp)).min; _wrap.anchorMax = ((Rect)(ref vp)).max; _wrap.offsetMin = Vector2.zero; _wrap.offsetMax = Vector2.zero; } } public void Unwrap() { if ((Object)(object)_wrap == (Object)null) { return; } if ((Object)(object)_root != (Object)null) { for (int i = 0; i < _kids.Count; i++) { if (!((Object)(object)_kids[i] == (Object)null)) { _kids[i].SetParent((Transform)(object)_root, false); _kids[i].SetSiblingIndex(Mathf.Min(i, ((Transform)_root).childCount - 1)); } } } _kids.Clear(); Object.Destroy((Object)(object)((Component)_wrap).gameObject); _wrap = null; _root = null; } } internal static class HudMirror { public static bool Active; private static Canvas _canvas; private static RenderMode _prevMode; private static Camera _prevCam; private static float _prevPlane; private static GameObject _camGo; private static GameObject _viewsGo; private static Camera _cam; private static RenderTexture _rt; private static bool _p2Failed; private static readonly MethodInfo _hudUpdate = Refl.Method(typeof(Hud), "Update"); private static readonly List<KeyValuePair<Component, MethodInfo>> _extra = new List<KeyValuePair<Component, MethodInfo>>(); public static bool InP2Pass; private static List<CanvasGroup> _groups; private static float[] _a1; private static float[] _a2; private static bool _a2Set; public static List<KeyValuePair<Component, MethodInfo>> Bars => _extra; private static void InitGroups() { if (_groups == null && !((Object)(object)_canvas == (Object)null)) { _groups = (from g in ((Component)_canvas).GetComponentsInChildren<CanvasGroup>(true) where (Object)(object)g != (Object)null && !RadialCopy.Manages(g) && !RadialState.Manages(g) select g).ToList(); _a1 = new float[_groups.Count]; _a2 = new float[_groups.Count]; _a2Set = false; } } private static void SaveAlpha(float[] a) { for (int i = 0; i < _groups.Count; i++) { if ((Object)(object)_groups[i] != (Object)null) { a[i] = _groups[i].alpha; } } } private static void LoadAlpha(float[] a) { for (int i = 0; i < _groups.Count; i++) { if ((Object)(object)_groups[i] != (Object)null) { _groups[i].alpha = a[i]; } } } public static bool Start() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) //IL_00de: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_029f: 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_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) Stop(); Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null || _hudUpdate == null) { SplitScreenPlugin.Log.LogWarning((object)"HUD mirror unavailable (Hud or Hud.Update not found); using the simple P2 HUD."); return false; } Canvas val = ((Component)instance).GetComponent<Canvas>(); if ((Object)(object)val == (Object)null) { val = ((Component)instance).GetComponentInParent<Canvas>(); } if ((Object)(object)val == (Object)null) { SplitScreenPlugin.Log.LogWarning((object)"HUD mirror: no canvas found."); return false; } val = (_canvas = val.rootCanvas); _prevMode = val.renderMode; _prevCam = val.worldCamera; _prevPlane = val.planeDistance; int sortingOrder = val.sortingOrder; _rt = new RenderTexture(Mathf.Max(16, Screen.width), Mathf.Max(16, Screen.height), 16, (RenderTextureFormat)0); ((Object)_rt).name = "SplitScreen_HUD_RT"; _rt.Create(); _camGo = new GameObject("SplitScreen_HudMirrorCam"); _cam = _camGo.AddComponent<Camera>(); ((Behaviour)_cam).enabled = false; _cam.clearFlags = (CameraClearFlags)2; _cam.backgroundColor = new Color(0f, 0f, 0f, 0f); _cam.cullingMask = 1 << ((Component)val).gameObject.layer; _cam.orthographic = true; _cam.orthographicSize = 1f; _cam.nearClipPlane = 0.1f; _cam.farClipPlane = 20f; _cam.allowHDR = false; _cam.allowMSAA = false; _cam.targetTexture = _rt; _cam.rect = SplitLayout.ViewportFor(0); val.renderMode = (RenderMode)1; val.worldCamera = _cam; val.planeDistance = 5f; _viewsGo = new GameObject("SplitScreen_HudViews", new Type[1] { typeof(RectTransform) }); _viewsGo.layer = SplitLayout.UiLayer; Canvas val2 = _viewsGo.AddComponent<Canvas>(); val2.renderMode = (RenderMode)0; val2.sortingOrder = sortingOrder; GameObject val3 = new GameObject("HudView", new Type[1] { typeof(RectTransform) }); val3.layer = SplitLayout.UiLayer; val3.transform.SetParent(_viewsGo.transform, false); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; RawImage val4 = val3.AddComponent<RawImage>(); val4.texture = (Texture)(object)_rt; ((Graphic)val4).raycastTarget = false; HotbarState.Reset(_extra); _extra.Clear(); Component[] componentsInChildren = ((Component)val).GetComponentsInChildren<Component>(true); foreach (Component val5 in componentsInChildren) { if (!((Object)(object)val5 == (Object)null) && !(((object)val5).GetType().Name != "HotkeyBar")) { MethodInfo methodInfo = Refl.Method(((object)val5).GetType(), "Update"); if (methodInfo != null) { _extra.Add(new KeyValuePair<Component, MethodInfo>(val5, methodInfo)); } } } _p2Failed = false; _groups = null; Active = true; SplitScreenPlugin.Log.LogInfo((object)("HUD mirror on. Canvas '" + ((Object)val).name + "', hotbars=" + _extra.Count)); return true; } public static void Stop() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_canvas != (Object)null) { _canvas.renderMode = _prevMode; _canvas.worldCamera = _prevCam; _canvas.planeDistance = _prevPlane; } _canvas = null; if ((Object)(object)_viewsGo != (Object)null) { Object.Destroy((Object)(object)_viewsGo); } if ((Object)(object)_camGo != (Object)null) { Object.Destroy((Object)(object)_camGo); } _viewsGo = null; _camGo = null; _cam = null; if ((Object)(object)_rt != (Object)null) { _rt.Release(); Object.Destroy((Object)(object)_rt); _rt = null; } HotbarState.Reset(_extra); _extra.Clear(); Active = false; } private static bool PauseP2() { if (MenuNav.SessionOpen || MenuNav.RawBuildVisible()) { return true; } if (RadialCopy.Active) { return false; } return RadialState.Open() && RadialState.Owner == 0; } public static void Render() { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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_0359: Unknown result type (might be due to invalid IL or missing references) if (!Active || (Object)(object)_cam == (Object)null || (Object)(object)_canvas == (Object)null) { return; } if ((Object)(object)LocalPlayerManager.Players[1] != (Object)null && MenuNav.SessionOpen && MenuNav.Owner == 1) { InitGroups(); HotbarState.SwapToP2(_extra); try { LocalPlayerManager.Enter(1); try { foreach (KeyValuePair<Component, MethodInfo> item in _extra) { if ((Object)(object)item.Key != (Object)null) { item.Value.Invoke(item.Key, null); } } HotbarState.RefreshIcons(_extra, LocalPlayerManager.Players[1]); } catch { } finally { LocalPlayerManager.Exit(); } RadialState.SetPassVisibility(1); RadialCopy.SetPass(1); Canvas.ForceUpdateCanvases(); _cam.rect = SplitLayout.ViewportFor(1); _cam.Render(); RadialCopy.SetPass(0); } finally { HotbarState.SwapBackToP1(_extra); } _cam.rect = SplitLayout.ViewportFor(DeviceMap.IsKbm(1) ? 1 : 0); return; } InitGroups(); SaveAlpha(_a1); RadialState.SetPassVisibility(0); RadialCopy.SetPass(0); Canvas.ForceUpdateCanvases(); _cam.rect = SplitLayout.ViewportFor(0); _cam.Render(); Hud instance = Hud.instance; if ((Object)(object)LocalPlayerManager.Players[1] != (Object)null && (Object)(object)instance != (Object)null && !_p2Failed && !PauseP2()) { if (_a2Set) { LoadAlpha(_a2); } else { SaveAlpha(_a2); } InP2Pass = true; HotbarState.SwapToP2(_extra); LocalPlayerManager.Enter(1); try { _hudUpdate.Invoke(instance, null); foreach (KeyValuePair<Component, MethodInfo> item2 in _extra) { if ((Object)(object)item2.Key != (Object)null) { item2.Value.Invoke(item2.Key, null); } } HotbarState.RefreshIcons(_extra, LocalPlayerManager.Players[1]); MinimapP2.Update(); } catch (Exception ex) { _p2Failed = true; Exception? obj2 = ex.InnerException ?? ex; SplitScreenPlugin.Log.LogError((object)("HUD mirror P2 pass failed (P2 HUD disabled): " + obj2)); } finally { LocalPlayerManager.Exit(); InP2Pass = false; } try { SaveAlpha(_a2); _a2Set = true; RadialState.SetPassVisibility(1); RadialCopy.SetPass(1); Canvas.ForceUpdateCanvases(); _cam.rect = SplitLayout.ViewportFor(1); _cam.Render(); LoadAlpha(_a1); RadialCopy.SetPass(0); } finally { HotbarState.SwapBackToP1(_extra); } } int slot = (DeviceMap.IsKbm(1) ? 1 : 0); _cam.rect = SplitLayout.ViewportFor(slot); } } [HarmonyPatch(typeof(GameCamera), "LateUpdate")] internal static class GameCameraPatch { private static void Postfix() { if (SplitLayout.Active) { SplitLayout.Reassert(); } } } internal static class P2Hud { private static GUIStyle _label; private static readonly MethodInfo _getHover = Refl.Method(typeof(Player), "GetHoverObject"); private static void Fill(Rect r, Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = c; GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } private static void Text(Rect r, string text, int size, TextAnchor anchor) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (_label == null) { _label = new GUIStyle(GUI.skin.label) { richText = true, wordWrap = true }; } _label.fontSize = size; _label.alignment = anchor; _label.normal.textColor = new Color(0f, 0f, 0f, 0.9f); GUI.Label(new Rect(((Rect)(ref r)).x + 1.5f, ((Rect)(ref r)).y + 1.5f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, _label); _label.normal.textColor = Color.white; GUI.Label(r, text, _label); } private static void Bar(Rect r, float frac, Color c, string text, float s) { //IL_0001: 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) //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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) Fill(r, new Color(0f, 0f, 0f, 0.6f)); Fill(new Rect(((Rect)(ref r)).x + 2f * s, ((Rect)(ref r)).y + 2f * s, (((Rect)(ref r)).width - 4f * s) * Mathf.Clamp01(frac), ((Rect)(ref r)).height - 4f * s), c); if (!string.IsNullOrEmpty(text)) { Text(r, text, Mathf.RoundToInt(13f * s), (TextAnchor)4); } } public static void Draw() { //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04d7: Unknown result type (might be due to invalid IL or missing references) Player val = LocalPlayerManager.Players[1]; if (!LocalPlayerManager.Joined || (Object)(object)val == (Object)null || !SplitLayout.Active || HudMirror.Active || (int)Event.current.type != 7) { return; } Rect val2 = SplitLayout.ViewportFor(1); float num = Screen.width; float num2 = Screen.heigh