Decompiled source of GK2 Coop v0.27.0
GK2Coop.dll
Decompiled 5 hours 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.IO.Compression; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DG.Tweening; using FlowCanvas; using GK2.FlowCanvasNodes; using HarmonyLib; using LazyBearTechnology; using Microsoft.CodeAnalysis; using Sirenix.Serialization; using Steamworks; using TMPro; using Unity.Collections; using Unity.Netcode; using Unity.Netcode.Transports.UTP; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GK2Coop")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GK2Coop")] [assembly: AssemblyTitle("GK2Coop")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace GK2Coop { internal static class ChestLocks { private const byte OpRequest = 1; private const byte OpGrant = 2; private const byte OpDeny = 3; private const byte OpRelease = 4; private const byte OpTable = 5; private static readonly Dictionary<string, ulong> locks = new Dictionary<string, ulong>(); private static string myOpenChest; private static float openedAt; private static ChestInteractionHandler pendingHandler; private static PlayerController pendingInteractor; private static string pendingChest; private static string grantedChest; private static ulong Me { get { if (CoopSession.Role != CoopRole.Host) { return CoopNetwork.LocalClientId; } return 0uL; } } public static void Reset() { locks.Clear(); myOpenChest = null; pendingHandler = null; pendingInteractor = null; pendingChest = null; grantedChest = null; } private static string Name(ulong id) { object obj; if (id == 0L) { obj = PlayerSync.Host?.Label ?? "the host"; } else { obj = PartnerProfiles.NameOf(id); if (obj == null) { obj = PlayerSync.Get(id)?.Label; if (obj == null) { return $"Player {id}"; } } } return (string)obj; } public static bool BeforeOpen(ChestInteractionHandler handler, PlayerController interactor, Wgo chest) { if (CoopSession.Role != CoopRole.None && CoopSession.KeepWorldRunning) { object obj; if (chest == null) { obj = null; } else { WgoData data = chest.Data; obj = ((data != null) ? data.UniqueId : null); } if (!((SGuid)obj == (SGuid)null)) { string id = chest.Data.UniqueId.Id; if (locks.TryGetValue(id, out var value) && value != Me) { CoopRunner.Think(Name(value) + " is using this chest."); return false; } if (CoopSession.Role == CoopRole.Host) { SetLock(id, 0uL); MarkOpen(id); return true; } if (grantedChest == id) { grantedChest = null; MarkOpen(id); return true; } pendingHandler = handler; pendingInteractor = interactor; pendingChest = id; Send(null, 1, id); return false; } } return true; } private static void MarkOpen(string uid) { myOpenChest = uid; openedAt = Time.unscaledTime; } public static void Tick() { if (myOpenChest != null && !(Time.unscaledTime - openedAt < 0.5f) && !AnyChestWindowOpen()) { string uid = myOpenChest; myOpenChest = null; if (CoopSession.Role == CoopRole.Host) { ReleaseLock(uid); } else if (CoopSession.Role == CoopRole.Client) { ContainerSync.SendChangedEverywhere(); Send(null, 4, uid); } } } private static bool AnyChestWindowOpen() { try { UIChestWindow window = LazyUI.GetWindow<UIChestWindow>(); int result; if (window == null || !((LazyWindow<UIBaseChestWindowData>)(object)window).IsShown) { UIConveyorChestWindow window2 = LazyUI.GetWindow<UIConveyorChestWindow>(); if (window2 == null || !((LazyWindow<UIBaseChestWindowData>)(object)window2).IsShown) { UIConveyorVegetablesChestWindow window3 = LazyUI.GetWindow<UIConveyorVegetablesChestWindow>(); if (window3 == null || !((LazyWindow<UIBaseChestWindowData>)(object)window3).IsShown) { result = ((((LazyWindow<UIBaseChestWindowData>)(object)LazyUI.GetWindow<UIConveyorWineChestWindow>())?.IsShown ?? false) ? 1 : 0); goto IL_004d; } } } result = 1; goto IL_004d; IL_004d: return (byte)result != 0; } catch { return false; } } public static void OnPlayerLeft(ulong clientId) { foreach (string item in (from p in locks where p.Value == clientId select p.Key).ToList()) { ReleaseLock(item); } } private static void SetLock(string uid, ulong owner) { locks[uid] = owner; BroadcastTable(); } private static void ReleaseLock(string uid) { if (locks.Remove(uid)) { BroadcastTable(); } } private unsafe static void BroadcastTable() { //IL_0009: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (CoopSession.Role != CoopRole.Host) { return; } FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 5; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); int count = locks.Count; ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (KeyValuePair<string, ulong> @lock in locks) { CoopMessages.WriteString(ref writer, @lock.Key); ulong value = @lock.Value; ((FastBufferWriter)(ref writer)).WriteValueSafe<ulong>(ref value, default(ForPrimitives)); } CoopMessages.SendToReadyClients("GK2Coop.Locks", writer, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void Send(ulong? to, byte op, string uid) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0014: 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_004d: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref op, default(ForPrimitives)); CoopMessages.WriteString(ref writer, uid); if (CoopSession.Role == CoopRole.Client) { CoopMessages.SendToHost("GK2Coop.Locks", writer, (NetworkDelivery)3); } else if (to.HasValue) { CoopMessages.SendTo("GK2Coop.Locks", to.Value, writer, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } public static void OnLocks(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); if (b == 5) { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); locks.Clear(); ulong value = default(ulong); for (int i = 0; i < num; i++) { string key = CoopMessages.ReadString(ref reader); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref value, default(ForPrimitives)); locks[key] = value; } return; } string text = CoopMessages.ReadString(ref reader); switch (b) { case 1: if (CoopSession.Role == CoopRole.Host) { if (locks.TryGetValue(text, out var value4) && value4 != sender) { Send(sender, 3, text); CoopLog.Info(Name(sender) + " can't open chest " + text + ": " + Name(value4) + " has it open."); } else { SetLock(text, sender); Send(sender, 2, text); } } break; case 4: { if (CoopSession.Role == CoopRole.Host && locks.TryGetValue(text, out var value3) && value3 == sender) { ReleaseLock(text); } break; } case 2: if (CoopSession.Role != CoopRole.Client) { break; } if (pendingChest == text && pendingHandler != null && (Object)(object)pendingInteractor != (Object)null) { grantedChest = text; ChestInteractionHandler val = pendingHandler; PlayerController val2 = pendingInteractor; pendingHandler = null; pendingInteractor = null; pendingChest = null; try { ((WGOInteractionHandlerBase)val).Interact(val2); break; } catch (Exception e) { CoopLog.Error("Opening the chest after the host's OK failed", e); Send(null, 4, text); break; } } Send(null, 4, text); break; case 3: if (CoopSession.Role == CoopRole.Client) { pendingHandler = null; pendingInteractor = null; pendingChest = null; CoopRunner.Think(locks.TryGetValue(text, out var value2) ? (Name(value2) + " is using this chest.") : "Someone else is using this chest."); } break; } } } [HarmonyPatch(typeof(ChestInteractionHandler), "Interact")] internal static class LockChestWhileOpen { private static bool Prefix(ChestInteractionHandler __instance, PlayerController interactor, Wgo ___assignedWgo, ref bool __result) { try { if (!ChestLocks.BeforeOpen(__instance, interactor, ___assignedWgo)) { __result = true; return false; } } catch (Exception e) { CoopLog.Error("Chest lock check failed; opening anyway", e); } return true; } } internal static class CombatSync { private struct HpEntry { public string Uid; public int Hp; public int Max; } private const byte OpFightState = 1; private const byte OpDamage = 2; private const byte OpPlayerHit = 3; private const byte OpKnockedOut = 4; private const byte OpHp = 5; private const byte OpWaves = 6; private const float HpInterval = 0.25f; private const float LocalHitGrace = 1.2f; private static readonly FieldInfo HpChangedField = AccessTools.Field(typeof(HPComponent), "OnHpChanged"); private static readonly FieldInfo FirstDamageField = AccessTools.Field(typeof(HPComponent), "OnFirstDamageDealt"); private static readonly FieldInfo FullHpField = AccessTools.Field(typeof(HPComponent), "OnFullHpRestored"); private static readonly MethodInfo EnsureLevelMethod = AccessTools.Method(typeof(FightingGameController), "EnsureFightingLevelLoaded", (Type[])null, (Type[])null); private static readonly FieldRef<FightingGameController, bool> WasLevelLoadedField = AccessTools.FieldRefAccess<FightingGameController, bool>("wasLevelLoaded"); private static readonly FieldRef<PlayerPhysicalBody, PlayerData> BodyPlayerDataField = AccessTools.FieldRefAccess<PlayerPhysicalBody, PlayerData>("playerData"); private static readonly FieldRef<PlayerData, SGuid> PlayerGuidField = AccessTools.FieldRefAccess<PlayerData, SGuid>("guid"); public static int Sent; public static int Applied; private static FightState hostState = (FightState)0; private static string hostLevel = ""; private static string hostScene = ""; private static readonly Dictionary<ulong, PlayerPhysicalBody> registered = new Dictionary<ulong, PlayerPhysicalBody>(); private static readonly Dictionary<HPComponent, ulong> avatarHp = new Dictionary<HPComponent, ulong>(); private static readonly HashSet<ulong> knockedOutPartners = new HashSet<ulong>(); private static readonly Dictionary<string, long> sentHp = new Dictionary<string, long>(); private static readonly Dictionary<ulong, string> hpSceneSentTo = new Dictionary<ulong, string>(); private static float nextHp; private static float nextTargets; private static float nextWaves; private static readonly FieldRef<FightingGameController, FightingLevelPresetProcessor> HostWavesField = AccessTools.FieldRefAccess<FightingGameController, FightingLevelPresetProcessor>("presetProcessor"); private static readonly MethodInfo WavesProgressSetter = AccessTools.PropertySetter(typeof(FightingLevelPresetProcessor), "CurrentProgress"); private static readonly MethodInfo WavesTotalSetter = AccessTools.PropertySetter(typeof(FightingLevelPresetProcessor), "TotalDuration"); private static readonly FieldInfo WavesProgressEvent = AccessTools.Field(typeof(FightingLevelPresetProcessor), "OnProgressChanged"); private static FightingLevelPresetProcessor shownWaves; private static bool timelineShown; private static float hostWavesProgress; private static float hostWavesTotal; private static FightState fightHere = (FightState)0; private static string fightLevel = ""; private static string fightScene = ""; private static bool levelShown; private static bool levelLoadedHere; private static string shownLevel = ""; private static bool armed; private static bool gearChecked; private static bool knockedOut; private static float nextStanceCheck; private static readonly HashSet<string> markedFighters = new HashSet<string>(); private static readonly Dictionary<string, float> recentLocalHits = new Dictionary<string, float>(); public static bool ApplyingRemote; public static bool FightAroundHost { get { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 if (CoopSession.Role == CoopRole.Client) { return (int)fightHere > 0; } return false; } } public static bool InHostFight { get { if (CoopSession.Role == CoopRole.Client) { return armed; } return false; } } public static void Reset() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (armed || levelShown) { try { LeaveFight("session ended"); } catch (Exception e) { CoopLog.Error("Putting the weapon away failed", e); } } HideTimeline(); hostWavesProgress = 0f; hostWavesTotal = 0f; hostState = (FightState)0; hostLevel = ""; hostScene = ""; registered.Clear(); avatarHp.Clear(); knockedOutPartners.Clear(); sentHp.Clear(); hpSceneSentTo.Clear(); fightHere = (FightState)0; fightLevel = ""; fightScene = ""; levelShown = false; levelLoadedHere = false; shownLevel = ""; armed = false; gearChecked = false; knockedOut = false; markedFighters.Clear(); recentLocalHits.Clear(); ApplyingRemote = false; Sent = 0; Applied = 0; } public static void Tick() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 if (CoopSession.Role == CoopRole.Host && CoopSession.HasReadyClients && CoopSession.IsInGame) { if (Time.unscaledTime >= nextHp) { nextHp = Time.unscaledTime + 0.25f; SendHp(); } if (Time.unscaledTime >= nextTargets) { nextTargets = Time.unscaledTime + 0.5f; UpdatePartnerTargets(); } if ((int)hostState == 2 && Time.unscaledTime >= nextWaves) { nextWaves = Time.unscaledTime + 0.25f; SendWaves(); } } else if (CoopSession.Role == CoopRole.Client && CoopSession.ClientInWorld) { TickStamina(); if (Time.unscaledTime >= nextStanceCheck) { nextStanceCheck = Time.unscaledTime + 0.5f; UpdateStance(); } } } private static void TickStamina() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!armed || MainGame.IsGamePaused) { return; } try { FightingGameController instance = LazySingleton<FightingGameController>.Instance; if ((Object)(object)instance != (Object)null && (int)instance.CurrentFightState != 0) { return; } PlayerData playerData = MainGame.PlayerData; if (playerData != null) { StaminaSystem staminaSystem = playerData.staminaSystem; if (staminaSystem != null) { staminaSystem.UpdateStaminaLogic(Time.deltaTime); } } } catch (Exception ex) { CoopLog.Debug("Refilling stamina failed: " + ex.Message); } } private static long Pack(HPComponent hp) { return ((long)hp.MaxHpValue << 32) | (uint)hp.Hp; } private static void SendHp() { HashSet<string> hashSet = NpcSync.ScenesWithPartners(); List<HpEntry> list = new List<HpEntry>(); foreach (string item in hashSet) { foreach (WgoData item2 in SceneObjects(item)) { HPComponent hpComponent = item2.HpComponent; if (hpComponent != null && hpComponent.MaxHpValue > 0 && !(item2.UniqueId == (SGuid)null)) { string id = item2.UniqueId.Id; long num = Pack(hpComponent); long value; bool num2 = sentHp.TryGetValue(id, out value); sentHp[id] = num; if (num2 && value != num && hpComponent.Hp > 0) { list.Add(new HpEntry { Uid = id, Hp = hpComponent.Hp, Max = hpComponent.MaxHpValue }); } } } } SendHpEntries(list, null); foreach (ulong item3 in CoopSession.ReadyClients.ToList()) { RemotePlayer remotePlayer = PlayerSync.Get(item3); if (remotePlayer == null || !remotePlayer.HasState || string.IsNullOrEmpty(remotePlayer.Scene) || (hpSceneSentTo.TryGetValue(item3, out var value2) && value2 == remotePlayer.Scene)) { continue; } hpSceneSentTo[item3] = remotePlayer.Scene; List<HpEntry> list2 = new List<HpEntry>(); foreach (WgoData item4 in SceneObjects(remotePlayer.Scene)) { HPComponent hpComponent2 = item4.HpComponent; if (hpComponent2 != null && hpComponent2.MaxHpValue > 0 && hpComponent2.Hp > 0 && hpComponent2.Hp < hpComponent2.MaxHpValue && item4.UniqueId != (SGuid)null) { list2.Add(new HpEntry { Uid = item4.UniqueId.Id, Hp = hpComponent2.Hp, Max = hpComponent2.MaxHpValue }); } } SendHpEntries(list2, item3); if (list2.Count > 0) { CoopLog.Debug($"Sent the HP of {list2.Count} damaged objects in '{remotePlayer.Scene}' to {remotePlayer.Label}."); } } } private static IEnumerable<WgoData> SceneObjects(string scene) { WorldData worldData = MainGame.WorldData; GameSceneData val = ((worldData != null) ? worldData.GetGameSceneDataById(scene) : null); if (val == null) { return Enumerable.Empty<WgoData>(); } return val.wgoDataList.Where((WgoData d) => d != null).ToList(); } private unsafe static void SendHpEntries(List<HpEntry> entries, ulong? onlyTo) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < entries.Count; i += 80) { List<HpEntry> list = entries.Skip(i).Take(80).ToList(); FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 5; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); int count = list.Count; ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (HpEntry item in list) { HpEntry current = item; CoopMessages.WriteString(ref writer, current.Uid); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref current.Hp, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref current.Max, default(ForPrimitives)); } if (onlyTo.HasValue) { CoopMessages.SendTo("GK2Coop.Combat", onlyTo.Value, writer, (NetworkDelivery)3); } else { CoopMessages.SendToReadyClients("GK2Coop.Combat", writer, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Sent++; } } public static void NoteLocalHit(WgoData data) { if (((data != null) ? data.UniqueId : null) != (SGuid)null && CoopSession.Role == CoopRole.Client) { recentLocalHits[data.UniqueId.Id] = Time.unscaledTime + 1.2f; } } public static void ApplyHitHp(WgoData data, int hp, int max) { HPComponent val = ((data != null) ? data.HpComponent : null); if (val == null || hp <= 0 || max <= 0) { return; } if (CoopSession.Role == CoopRole.Host) { if (hp < val.Hp) { SetHp(data, hp, max); } } else { ApplyHostHp(data, hp, max); } } private static void ApplyHostHp(WgoData data, int hp, int max) { HPComponent hpComponent = data.HpComponent; if (hpComponent != null && (hp <= hpComponent.Hp || !recentLocalHits.TryGetValue(data.UniqueId.Id, out var value) || !(Time.unscaledTime < value))) { SetHp(data, hp, max); } } private static void SetHp(WgoData data, int hp, int max) { HPComponent hpComponent = data.HpComponent; if (hpComponent == null || hpComponent.isDeathDelayed || (hpComponent.Hp == hp && hpComponent.MaxHpValue == max)) { return; } bool flag = !hpComponent.WasDamagedAtLeastOnce; if (hpComponent.MaxHpValue != max) { hpComponent.SetCustomHpValue(max, true); } hpComponent.SetCustomHpValue(Mathf.Clamp(hp, 1, max), false); bool flag2 = hp >= max; hpComponent.wasDamagedAtLeastOnce = !flag2; try { if (flag && !flag2) { (FirstDamageField?.GetValue(hpComponent) as Action)?.Invoke(); } (HpChangedField?.GetValue(hpComponent) as Action<HPComponent>)?.Invoke(hpComponent); if (flag2) { (FullHpField?.GetValue(hpComponent) as Action)?.Invoke(); } } catch (Exception ex) { CoopLog.Warn("HP change listeners on " + ((ObjectLinkedToDefinition<WGODef>)(object)data).id + " failed: " + ex.Message); } Applied++; } public unsafe static void OnHostFightState(FightingGameController controller, FightState state) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (CoopSession.Role == CoopRole.Host) { hostState = state; string value = (((Object)(object)controller.CurrentLevel != (Object)null) ? controller.CurrentLevel.id : ""); if (!string.IsNullOrEmpty(value)) { hostLevel = value; } hostScene = MainGame.PlayerData?.currentGameSceneId ?? ""; CoopLog.Info($"Host fight state: {state} (level '{hostLevel}', area '{hostScene}')."); if ((int)state != 2) { UnregisterPartners("fight is " + ((object)(*(FightState*)(&state))/*cast due to .constrained prefix*/).ToString()); knockedOutPartners.Clear(); } if (CoopSession.HasReadyClients) { SendFightState(null); } } } private unsafe static void SendFightState(ulong? onlyTo) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0010: 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_001e: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 1; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); b = (byte)hostState; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.WriteString(ref writer, hostLevel ?? ""); CoopMessages.WriteString(ref writer, hostScene ?? ""); if (onlyTo.HasValue) { CoopMessages.SendTo("GK2Coop.Combat", onlyTo.Value, writer, (NetworkDelivery)3); } else { CoopMessages.SendToReadyClients("GK2Coop.Combat", writer, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Sent++; } public static void OnClientReady(ulong clientId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) hpSceneSentTo.Remove(clientId); if ((int)hostState != 0) { SendFightState(clientId); } } private static void UpdatePartnerTargets() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 FightingGameController instance = LazySingleton<FightingGameController>.Instance; if ((Object)(object)instance == (Object)null || (int)instance.CurrentFightState != 2) { if (registered.Count > 0) { UnregisterPartners("no fight"); } return; } string text = MainGame.PlayerData?.currentGameSceneId; foreach (ulong item in CoopSession.ReadyClients.ToList()) { RemotePlayer remotePlayer = PlayerSync.Get(item); bool flag = remotePlayer != null && (Object)(object)remotePlayer.Body != (Object)null && remotePlayer.Visible && remotePlayer.HasState && remotePlayer.Scene == text && !knockedOutPartners.Contains(item); registered.TryGetValue(item, out var value); if (flag && (Object)(object)value != (Object)(object)remotePlayer.Body) { if ((Object)(object)value != (Object)null) { Unregister(item, value); } Register(item, remotePlayer); } else if (!flag && (Object)(object)value != (Object)null) { Unregister(item, value); } } foreach (ulong item2 in registered.Keys.Where((ulong c) => !CoopSession.ReadyClients.Contains(c)).ToList()) { Unregister(item2, registered[item2]); } } private static void Register(ulong clientId, RemotePlayer remote) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown try { PlayerData val = (((Object)(object)remote.Controller != (Object)null) ? remote.Controller.PlayerData : null); if (val != null) { if (PlayerGuidField.Invoke(val) == (SGuid)null || PlayerGuidField.Invoke(val).Equals(MainGame.PlayerData.Guid)) { PlayerGuidField.Invoke(val) = new SGuid(); } BodyPlayerDataField.Invoke(remote.Body) = val; val.hpComponent.RestoreFullHp(); remote.Body.IsActiveCombatant = true; LazySingleton<FightingGameController>.Instance.RegisterTargetNonPersistent((ICombatEntity)(object)remote.Body, -1, -1, true); registered[clientId] = remote.Body; avatarHp[val.hpComponent] = clientId; CoopLog.Info(remote.Label + " is now a fight target."); } } catch (Exception e) { CoopLog.Error("Making " + remote.Label + " a fight target failed", e); } } private static void Unregister(ulong clientId, PlayerPhysicalBody body) { registered.Remove(clientId); foreach (HPComponent item in (from p in avatarHp where p.Value == clientId select p.Key).ToList()) { avatarHp.Remove(item); } try { if ((Object)(object)body != (Object)null) { LazySingleton<FightingGameController>.Instance.UnregisterTarget((ICombatEntity)(object)body); body.IsActiveCombatant = true; } } catch (Exception ex) { CoopLog.Warn("Removing a partner from the fight targets failed: " + ex.Message); } } public static void UnregisterPartners(string why) { if (registered.Count == 0) { return; } CoopLog.Info($"Removing {registered.Count} partners from the fight targets ({why})."); foreach (KeyValuePair<ulong, PlayerPhysicalBody> item in registered.ToList()) { Unregister(item.Key, item.Value); } } public unsafe static void OnHpDamaged(HPComponent component, int before) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (CoopSession.Role != CoopRole.Host || component == null || !avatarHp.TryGetValue(component, out var value)) { return; } int num = before - component.Hp; component.RestoreFullHp(); if (num > 0) { FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 3; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref num, default(ForPrimitives)); CoopMessages.SendTo("GK2Coop.Combat", value, writer, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Sent++; CoopLog.Debug($"{PlayerSync.Get(value)?.Label ?? value.ToString()} was hit for {num}."); } } private static void HostApplyPartnerDamage(ulong sender, string uid, int damage) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) WorldData worldData = MainGame.WorldData; WgoData val = ((worldData != null) ? worldData.GetWgoData(SGuid.Parse(uid)) : null); HPComponent val2 = ((val != null) ? val.HpComponent : null); if (val2 == null || damage <= 0) { return; } Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(val.UniqueId); val2.ApplyDamage(damage); Applied++; CoopLog.Debug($"{PlayerSync.Get(sender)?.Label ?? sender.ToString()} hit {((ObjectLinkedToDefinition<WGODef>)(object)val).id} for {damage} (HP {val2.Hp}/{val2.MaxHpValue})."); if ((Object)(object)wgoViewGlobal == (Object)null) { return; } try { PlayerPhysicalBody physicalBody = MainGame.PlayerController.PhysicalBody; Vector3 val3 = PlayerSync.Get(sender)?.Position ?? ((Component)physicalBody).transform.position; Vector3 val4 = val.Position - val3; Vector3 normalized = ((Vector3)(ref val4)).normalized; AttackContext val5 = default(AttackContext); ((AttackContext)(ref val5))..ctor((ICombatEntity)(object)physicalBody, (TeamType)0, (FighterDef)null, (ItemDef)null, val3, normalized, val.Position, damage, false, (AttackComponent)null, (DamageEffectSettings)null); wgoViewGlobal.OnOtherCombatTargetHitMe(val5); } catch (Exception ex) { CoopLog.Warn("On-hit logic for " + ((ObjectLinkedToDefinition<WGODef>)(object)val).id + " failed: " + ex.Message); } } private static void UpdateStance() { //IL_0000: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if ((int)fightHere == 0) { gearChecked = false; } else if (!gearChecked) { PlayerController playerController = MainGame.PlayerController; if (((playerController != null) ? playerController.PlayerData : null) != null) { gearChecked = true; FightGear.EnsureOwn(MainGame.PlayerController, withSword: true); } } PlayerController playerController2 = MainGame.PlayerController; string text = ((playerController2 == null) ? null : playerController2.PlayerData?.currentGameSceneId); bool flag = (int)fightHere != 0 && !string.IsNullOrEmpty(text) && text == fightScene; if (flag && (!levelShown || shownLevel != fightLevel)) { ShowLevel(); } bool flag2 = flag && (int)fightHere == 2 && !knockedOut; if (flag2 && !armed) { Arm(); } else if (!flag2 && armed) { Disarm(); } if (!flag && levelShown) { LeaveFight(((int)fightHere == 0) ? "the fight ended" : "we left the fight's area"); } else if (flag) { MarkFighters(text); } } private static void ShowLevel() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 levelShown = true; shownLevel = fightLevel; if (string.IsNullOrEmpty(fightLevel)) { return; } FightingGameController instance = LazySingleton<FightingGameController>.Instance; try { bool flag = WasLevelLoadedField.Invoke(instance); WasLevelLoadedField.Invoke(instance) = false; EnsureLevelMethod?.Invoke(instance, new object[1] { fightLevel }); levelLoadedHere = WasLevelLoadedField.Invoke(instance); WasLevelLoadedField.Invoke(instance) = flag; } catch (Exception e) { CoopLog.Error("Loading fight level '" + fightLevel + "' here failed", e); } try { FightingLevel fightingLevel = MainGame.GetFightingLevel(fightLevel); if ((Object)(object)fightingLevel != (Object)null) { fightingLevel.ApplyStageId(((int)fightHere == 2) ? 4 : 3); fightingLevel.SetActive(true); fightingLevel.SetBorderObjectsActive(true); } CoopLog.Info($"Showing the host's fight level '{fightLevel}' (loaded here: {levelLoadedHere}, found: {(Object)(object)fightingLevel != (Object)null})."); } catch (Exception e2) { CoopLog.Error("Showing fight level '" + fightLevel + "' failed", e2); } } private static void Arm() { armed = true; try { PlayerController playerController = MainGame.PlayerController; MainGame.PlayerData.RemoveInteractingItem(); FightGear.EnsureOwn(playerController, withSword: true); playerController.SetArmorView(true, (int?)null, true); FightGear.DrawWeapon(playerController); Item sword = playerController.Sword; Item bow = playerController.Bow; ItemDef val = ((sword != null && ((ObjectLinkedToDefinition<ItemDef>)(object)sword).id != "empty") ? ((ObjectLinkedToDefinition<ItemDef>)(object)sword).Definition : ((bow != null && ((ObjectLinkedToDefinition<ItemDef>)(object)bow).id != "empty") ? ((ObjectLinkedToDefinition<ItemDef>)(object)bow).Definition : null)); MainGame.PlayerData.staminaSystem.SetMax(); playerController.View.UpdateStaminaBarState(); try { FightingLevel fightingLevel = MainGame.GetFightingLevel(fightLevel); if (fightingLevel != null) { fightingLevel.ApplyStageId(4); } } catch { } ShowTimeline(); string text = PlayerSync.Host?.Label ?? "the host"; CoopRunner.Toast("Fight! Help " + text + ": attack the enemies.", 6f); CoopLog.Info("Joined " + text + "'s fight with " + ((val != null) ? ((BalanceBaseObject)val).id : "the default sword") + "."); } catch (Exception e) { CoopLog.Error("Getting the weapon out failed", e); } } private unsafe static void SendWaves() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) FightingLevelPresetProcessor val = HostWavesField.Invoke(LazySingleton<FightingGameController>.Instance); if ((Object)(object)val == (Object)null || !val.IsPlaying) { return; } FastBufferWriter val2 = CoopMessages.NewWriter(); try { FastBufferWriter writer = val2; byte b = 6; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); float currentProgress = val.CurrentProgress; ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref currentProgress, default(ForPrimitives)); currentProgress = val.TotalDuration; ((FastBufferWriter)(ref writer)).WriteValueSafe<float>(ref currentProgress, default(ForPrimitives)); CoopMessages.SendToReadyClients("GK2Coop.Combat", writer, (NetworkDelivery)1); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private static void ShowTimeline() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //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) //IL_00a1: Expected O, but got Unknown if (timelineShown) { return; } try { FightingLevel fightingLevel = MainGame.GetFightingLevel(fightLevel); HUD val = LazyUI.Get<HUD>(); if ((Object)(object)((fightingLevel != null) ? fightingLevel.FightingLevelPreset : null) == (Object)null || (Object)(object)val == (Object)null) { CoopLog.Debug("No wave timeline for '" + fightLevel + "' here (level " + (((Object)(object)fightingLevel != (Object)null) ? "has no preset" : "not found") + ")."); return; } if ((Object)(object)shownWaves == (Object)null) { GameObject val2 = new GameObject("GK2Coop fight waves"); Object.DontDestroyOnLoad((Object)val2); shownWaves = val2.AddComponent<FightingLevelPresetProcessor>(); } SetShownWaves(hostWavesProgress, hostWavesTotal); val.DrawFightingTimeline(new UIFightingTimelineRendererData(fightingLevel.FightingLevelPreset, shownWaves, fightingLevel)); val.SetMode((HUDMode)1); timelineShown = true; CoopLog.Info("Showing the host's wave timeline for '" + fightLevel + "'."); } catch (Exception ex) { CoopLog.Warn("Showing the wave timeline failed: " + ex.Message); } } private static void HideTimeline() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if (!timelineShown) { return; } timelineShown = false; try { HUD val = LazyUI.Get<HUD>(); if ((Object)(object)val != (Object)null && (int)val.Mode == 1) { val.HideFightingTimeline(); val.SetMode((HUDMode)0); } } catch (Exception ex) { CoopLog.Warn("Putting the HUD back after the fight failed: " + ex.Message); } } private static void SetShownWaves(float progress, float total) { if (!((Object)(object)shownWaves == (Object)null)) { WavesTotalSetter?.Invoke(shownWaves, new object[1] { total }); WavesProgressSetter?.Invoke(shownWaves, new object[1] { Mathf.Clamp(progress, 0f, Mathf.Max(total, progress)) }); (WavesProgressEvent?.GetValue(shownWaves) as Action<float>)?.Invoke(shownWaves.ProgressNormalized); } } private static void Disarm() { HideTimeline(); armed = false; try { PlayerController playerController = MainGame.PlayerController; playerController.AttackComponent.UnequipWeapon(); playerController.SetArmorView(false, (int?)null, true); playerController.View.UpdateStaminaBarState(); } catch (Exception e) { CoopLog.Error("Putting the weapon away failed", e); } } private static void LeaveFight(string why) { if (armed) { Disarm(); } UnmarkFighters(); if (levelShown && !string.IsNullOrEmpty(shownLevel)) { try { FightingLevel fightingLevel = MainGame.GetFightingLevel(shownLevel); if ((Object)(object)fightingLevel != (Object)null) { fightingLevel.SetActive(false); fightingLevel.SetBorderObjectsActive(false); } GameSceneData val = default(GameSceneData); GameSceneConfig val2 = default(GameSceneConfig); if (levelLoadedHere && MainGame.WorldData.TryGetGameSceneDataForContent(shownLevel, ref val, ref val2)) { val.RemoveFightingLevelData(shownLevel); } } catch (Exception e) { CoopLog.Error("Hiding fight level '" + shownLevel + "' failed", e); } } try { PlayerData playerData = MainGame.PlayerData; if (playerData != null) { HPComponent hpComponent = playerData.hpComponent; if (hpComponent != null) { hpComponent.RestoreFullHp(); } } } catch { } CoopLog.Info("Left the fight (" + why + ")."); levelShown = false; levelLoadedHere = false; shownLevel = ""; knockedOut = false; } private static void MarkFighters(string scene) { HashSet<string> hashSet = GameBalance.Me?.fighterWgoIdsCache; if (hashSet == null) { return; } foreach (WgoData item in SceneObjects(scene)) { if (!(item.UniqueId == (SGuid)null) && hashSet.Contains(((ObjectLinkedToDefinition<WGODef>)(object)item).id)) { Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(item.UniqueId); if ((Object)(object)wgoViewGlobal != (Object)null && !wgoViewGlobal.IsActiveCombatant) { wgoViewGlobal.IsActiveCombatant = true; markedFighters.Add(item.UniqueId.Id); } } } } private static void UnmarkFighters() { foreach (string markedFighter in markedFighters) { try { Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(SGuid.Parse(markedFighter)); if ((Object)(object)wgoViewGlobal != (Object)null) { wgoViewGlobal.IsActiveCombatant = false; } } catch { } } markedFighters.Clear(); } public unsafe static bool OnLocalAttackHit(AttackComponent attacker, ICombatEntity target, AttackContext context) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) if (CoopSession.Role != CoopRole.Client || !CoopSession.ClientInWorld || !Plugin.HostRunsWorld.Value || ApplyingRemote) { return true; } PlayerController playerController = MainGame.PlayerController; if ((Object)(object)playerController == (Object)null || (Object)(object)attacker != (Object)(object)playerController.AttackComponent) { return false; } Wgo val = (Wgo)(object)((target is Wgo) ? target : null); if (val != null) { WgoData data = val.Data; if (!(((data != null) ? data.UniqueId : null) == (SGuid)null) && !knockedOut) { int num = 0; try { num = target.ArmorValue; } catch { } int num2 = Mathf.Clamp(((AttackContext)(ref context)).Damage - num, 0, int.MaxValue); if (num2 > 0) { FastBufferWriter val2 = CoopMessages.NewWriter(); try { FastBufferWriter writer = val2; byte b = 2; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.WriteString(ref writer, val.Data.UniqueId.Id); ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref num2, default(ForPrimitives)); CoopMessages.SendToHost("GK2Coop.Combat", writer, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } Sent++; } return false; } } return false; } private unsafe static void OnPlayerHit(int damage) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) HPComponent val = MainGame.PlayerData?.hpComponent; if (val == null || knockedOut || damage <= 0) { return; } if (val.Hp - damage > 0) { val.ApplyDamage(damage); return; } val.SetCustomHpValue(1, false); val.wasDamagedAtLeastOnce = true; try { (HpChangedField?.GetValue(val) as Action<HPComponent>)?.Invoke(val); } catch { } knockedOut = true; if (armed) { Disarm(); } FastBufferWriter val2 = CoopMessages.NewWriter(); try { FastBufferWriter writer = val2; byte b = 4; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.SendToHost("GK2Coop.Combat", writer, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } CoopRunner.Toast("You're knocked out until the fight ends.", 8f); CoopLog.Info("Knocked out in the host's fight."); } public static void OnCombat(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: 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_0234: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Invalid comparison between Unknown and I4 //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); if (CoopSession.Role == CoopRole.Client && !CoopSession.ClientInWorld && b != 1) { return; } switch (b) { case 1: if (CoopSession.Role == CoopRole.Client) { byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b2, default(ForPrimitives)); fightLevel = CoopMessages.ReadString(ref reader); fightScene = CoopMessages.ReadString(ref reader); FightState val2 = fightHere; fightHere = (FightState)b2; CoopLog.Info($"Host fight state {fightHere} (level '{fightLevel}', area '{fightScene}')."); if ((int)fightHere == 0 && (int)val2 != 0 && levelShown) { CoopRunner.Toast("The fight is over."); } else if ((int)fightHere == 1 && (int)val2 == 0) { CoopRunner.Toast((PlayerSync.Host?.Label ?? "The host") + " is getting ready for a fight."); } if (CoopSession.ClientInWorld) { UpdateStance(); } } break; case 2: if (CoopSession.Role == CoopRole.Host) { string uid = CoopMessages.ReadString(ref reader); int damage2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref damage2, default(ForPrimitives)); if (!knockedOutPartners.Contains(sender)) { HostApplyPartnerDamage(sender, uid, damage2); } } break; case 3: if (CoopSession.Role == CoopRole.Client) { int damage = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref damage, default(ForPrimitives)); OnPlayerHit(damage); } break; case 4: if (CoopSession.Role == CoopRole.Host) { knockedOutPartners.Add(sender); if (registered.TryGetValue(sender, out var value)) { Unregister(sender, value); } CoopRunner.Toast((PlayerSync.Get(sender)?.Label ?? "A partner") + " is knocked out."); CoopLog.Info((PlayerSync.Get(sender)?.Label ?? sender.ToString()) + " is knocked out."); } break; case 6: if (CoopSession.Role == CoopRole.Client) { float progress = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref progress, default(ForPrimitives)); float total = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref total, default(ForPrimitives)); hostWavesProgress = progress; hostWavesTotal = total; if (timelineShown) { SetShownWaves(progress, total); } } break; case 5: { if (CoopSession.Role != CoopRole.Client) { break; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); int hp = default(int); int max = default(int); for (int i = 0; i < num; i++) { string text = CoopMessages.ReadString(ref reader); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref hp, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref max, default(ForPrimitives)); WorldData worldData = MainGame.WorldData; WgoData val = ((worldData != null) ? worldData.GetWgoData(SGuid.Parse(text)) : null); if (val != null) { ApplyHostHp(val, hp, max); } } break; } } } public static string Describe() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (CoopSession.Role != CoopRole.Host) { return $"fight={fightHere} level='{fightLevel}' shown={levelShown} armed={armed} knockedOut={knockedOut} marked={markedFighters.Count} applied={Applied}"; } return $"fight={hostState} level='{hostLevel}' targets={registered.Count} hpTracked={sentHp.Count} sent={Sent} applied={Applied}"; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class PartnerFightBars { private static void Postfix(PlayerView __instance, ref List<LazyWidgetDataBase> __result) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown try { if (!CombatSync.InHostFight || __result == null) { return; } PlayerController playerController = MainGame.PlayerController; if (!((Object)(object)__instance != (Object)(object)((playerController != null) ? playerController.View : null))) { HPComponent val = MainGame.PlayerData?.hpComponent; if (val != null && !__result.Any((LazyWidgetDataBase w) => w is HpBarPlayerWidgetData)) { __result.Add((LazyWidgetDataBase)new HpBarPlayerWidgetData(val, -1f, -1f)); } if (!__result.Any((LazyWidgetDataBase w) => w is StaminaBarPlayerWidgetData)) { __result.Add((LazyWidgetDataBase)new StaminaBarPlayerWidgetData()); } } } catch (Exception ex) { CoopLog.Debug("Showing our fight bars failed: " + ex.Message); } } } [HarmonyPatch(typeof(FightingGameController), "SetFightState")] internal static class MirrorFightState { private static void Postfix(FightingGameController __instance, FightState newState) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) try { CombatSync.OnHostFightState(__instance, newState); } catch (Exception e) { CoopLog.Error("Mirroring the fight state failed", e); } } } [HarmonyPatch(typeof(FightingGameController), "Stop")] internal static class PartnersLeaveFightTargets { private static void Prefix() { CombatSync.UnregisterPartners("fight stopping"); } } [HarmonyPatch(typeof(HPComponent), "ApplyDamage")] internal static class RelayPartnerDamage { private static void Prefix(HPComponent __instance, out int __state) { __state = __instance.Hp; } private static void Postfix(HPComponent __instance, int __state) { CombatSync.OnHpDamaged(__instance, __state); } } [HarmonyPatch(typeof(AttackComponent), "HandleHit")] internal static class PartnerHitsGoToHost { private static bool Prefix(AttackComponent __instance, ICombatEntity target, AttackContext attackContext) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { return CombatSync.OnLocalAttackHit(__instance, target, attackContext); } catch (Exception e) { CoopLog.Error("Forwarding our hit failed", e); return true; } } } internal static class ContainerSync { private enum Slot : byte { Inventory, CraftInventory } private const byte OpContents = 1; private const float PollInterval = 1f; private static readonly Dictionary<string, int> signatures = new Dictionary<string, int>(); private static readonly Dictionary<ulong, string> sentSceneTo = new Dictionary<ulong, string>(); private static float nextPoll; private static readonly Dictionary<Inventory, KeyValuePair<WgoData, Slot>> owners = new Dictionary<Inventory, KeyValuePair<WgoData, Slot>>(); private static readonly HashSet<Inventory> announced = new HashSet<Inventory>(); public static int Sent; public static int Applied; private const float ClientReach = 4f; public static void Reset() { signatures.Clear(); sentSceneTo.Clear(); owners.Clear(); announced.Clear(); nextPoll = 0f; Sent = 0; Applied = 0; } public static void OnInventoryEvent(Inventory inventory) { if (inventory != null && owners.ContainsKey(inventory)) { announced.Add(inventory); } } private static void SendAnnounced() { //IL_0032: 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_0048: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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) if (announced.Count == 0) { return; } bool flag = CoopSession.Role == CoopRole.Client; Vector3 val; if (flag) { PlayerController playerController = MainGame.PlayerController; if ((Object)(object)((playerController != null) ? playerController.PhysicalBody : null) != (Object)null) { val = ((Component)MainGame.PlayerController.PhysicalBody).transform.position; goto IL_004d; } } val = Vector3.zero; goto IL_004d; IL_004d: Vector3 val2 = val; foreach (Inventory item in announced.ToList()) { if (!owners.TryGetValue(item, out var value)) { continue; } WgoData key = value.Key; if (((key != null) ? key.UniqueId : null) == (SGuid)null) { continue; } WgoData key2 = value.Key; if (flag) { if (ConveyorSync.IsBelt(key2)) { continue; } Vector3 val3 = key2.Position - val2; if (((Vector3)(ref val3)).sqrMagnitude > 16f) { continue; } } List<Item> list = Items(key2, value.Value); if (list != null) { string key3 = Key(key2, value.Value); int num = Signature(list); int value2; bool num2 = signatures.TryGetValue(key3, out value2); signatures[key3] = num; if (num2 && value2 != num) { Send(key2, value.Value, list, null); } } } announced.Clear(); } private static void Watch(WgoData data) { if (data.Inventory != null && !owners.ContainsKey(data.Inventory)) { owners[data.Inventory] = new KeyValuePair<WgoData, Slot>(data, Slot.Inventory); } if (data.CraftInventory != null && !owners.ContainsKey(data.CraftInventory)) { owners[data.CraftInventory] = new KeyValuePair<WgoData, Slot>(data, Slot.CraftInventory); } } public static void Tick() { bool flag = CoopSession.Role == CoopRole.Host && CoopSession.HasReadyClients && CoopSession.IsInGame; bool flag2 = CoopSession.Role == CoopRole.Client && CoopSession.ClientInWorld; if (!flag && !flag2) { announced.Clear(); return; } SendAnnounced(); if (Time.unscaledTime < nextPoll) { return; } if (owners.Count > 20000) { owners.Clear(); } nextPoll = Time.unscaledTime + 1f; if (flag) { foreach (ulong item in CoopSession.ReadyClients.ToList()) { RemotePlayer remotePlayer = PlayerSync.Get(item); if (remotePlayer != null && remotePlayer.HasState && !string.IsNullOrEmpty(remotePlayer.Scene) && (!sentSceneTo.TryGetValue(item, out var value) || value != remotePlayer.Scene)) { sentSceneTo[item] = remotePlayer.Scene; int num = SendScene(remotePlayer.Scene, item); CoopLog.Debug($"Sent {num} containers in '{remotePlayer.Scene}' to {remotePlayer.Label}."); } } { foreach (string item2 in new HashSet<string>(from c in CoopSession.ReadyClients select PlayerSync.Get(c)?.Scene into s where !string.IsNullOrEmpty(s) select s)) { SendChanged(item2, null); } return; } } PlayerController playerController = MainGame.PlayerController; string text = ((playerController == null) ? null : playerController.PlayerData?.currentGameSceneId); if (!string.IsNullOrEmpty(text)) { SendChanged(text, null); } } private static IEnumerable<WgoData> Containers(string sceneId) { WorldData worldData = MainGame.WorldData; GameSceneData val = ((worldData != null) ? worldData.GetGameSceneDataById(sceneId) : null); if (val == null) { yield break; } foreach (WgoData item in val.wgoDataList.ToList()) { if (((item != null) ? item.UniqueId : null) != (SGuid)null && ((ObjectLinkedToDefinition<WGODef>)(object)item).Definition != null && !((ObjectLinkedToDefinition<WGODef>)(object)item).Definition.hasRefToOtherWgoInventory) { yield return item; } } } private static List<Item> Items(WgoData data, Slot slot) { Inventory obj = ((slot == Slot.Inventory) ? data.Inventory : data.CraftInventory); if (obj == null) { return null; } Item data2 = obj.Data; if (data2 == null) { return null; } return data2.Inventory; } private static int Signature(List<Item> items, int depth = 0) { if (items == null) { return 0; } int num = 17 + items.Count; foreach (Item item in items) { if (item == null) { num *= 31; continue; } num = num * 31 + (((ObjectLinkedToDefinition<ItemDef>)(object)item).id?.GetHashCode() ?? 0); num = num * 31 + item.Count; if (depth < 2 && item.Inventory != null && item.Inventory.Count > 0) { num = num * 31 + Signature(item.Inventory, depth + 1); } } return num; } private static string Key(WgoData data, Slot slot) { return data.UniqueId.Id + ((slot == Slot.Inventory) ? "" : "#craft"); } private static void SendChanged(string sceneId, ulong? onlyTo, bool ignoreReach = false) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) bool flag = CoopSession.Role == CoopRole.Client; Vector3 val; if (flag) { PlayerController playerController = MainGame.PlayerController; if ((Object)(object)((playerController != null) ? playerController.PhysicalBody : null) != (Object)null) { val = ((Component)MainGame.PlayerController.PhysicalBody).transform.position; goto IL_0040; } } val = Vector3.zero; goto IL_0040; IL_0040: Vector3 val2 = val; foreach (WgoData item in Containers(sceneId)) { Watch(item); if (flag && ConveyorSync.IsBelt(item)) { continue; } int num; if (!ignoreReach && flag) { Vector3 val3 = item.Position - val2; num = ((((Vector3)(ref val3)).sqrMagnitude <= 16f) ? 1 : 0); } else { num = 1; } bool flag2 = (byte)num != 0; Slot[] array = new Slot[2] { Slot.Inventory, Slot.CraftInventory }; foreach (Slot slot in array) { List<Item> list = Items(item, slot); if (list != null) { string key = Key(item, slot); int num2 = Signature(list); int value; bool num3 = signatures.TryGetValue(key, out value); signatures[key] = num2; if (num3 && value != num2 && flag2) { Send(item, slot, list, onlyTo); } } } } } public static void SendChangedEverywhere() { if (CoopSession.Role == CoopRole.Client && CoopSession.ClientInWorld) { PlayerController playerController = MainGame.PlayerController; string text = ((playerController == null) ? null : playerController.PlayerData?.currentGameSceneId); if (!string.IsNullOrEmpty(text)) { SendChanged(text, null, ignoreReach: true); } } } private static int SendScene(string sceneId, ulong clientId) { int num = 0; foreach (WgoData item in Containers(sceneId)) { Watch(item); Slot[] array = new Slot[2] { Slot.Inventory, Slot.CraftInventory }; foreach (Slot slot in array) { List<Item> list = Items(item, slot); if (list != null && list.Count != 0) { signatures[Key(item, slot)] = Signature(list); Send(item, slot, list, clientId); num++; } } } return num; } private unsafe static void Send(WgoData data, Slot slot, List<Item> items, ulong? onlyTo, ulong? except = null) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) byte[] bytes; try { bytes = SerializationUtility.SerializeValue<List<Item>>(items, (DataFormat)0, (SerializationContext)null); } catch (Exception e) { CoopLog.Error("Serializing the contents of " + ((ObjectLinkedToDefinition<WGODef>)(object)data).id + " failed", e); return; } FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 1; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.WriteString(ref writer, data.UniqueId.Id); b = (byte)slot; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.WriteBytes(ref writer, bytes); if (CoopSession.Role == CoopRole.Client) { CoopMessages.SendToHost("GK2Coop.Containers", writer, (NetworkDelivery)3); } else if (onlyTo.HasValue) { CoopMessages.SendTo("GK2Coop.Containers", onlyTo.Value, writer, (NetworkDelivery)3); } else { CoopMessages.SendToReadyClients("GK2Coop.Containers", writer, (NetworkDelivery)4, except); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Sent++; CoopLog.Debug($"Sent contents of {((ObjectLinkedToDefinition<WGODef>)(object)data).id} ({slot}, {items.Count} stacks)."); } public static void OnContainers(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); if (b != 1) { return; } string text = CoopMessages.ReadString(ref reader); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b2, default(ForPrimitives)); byte[] array = CoopMessages.ReadBytes(ref reader); Slot slot = (Slot)b2; if (CoopSession.Role == CoopRole.Client && !CoopSession.ClientInWorld) { return; } WorldData worldData = MainGame.WorldData; WgoData val = ((worldData != null) ? worldData.GetWgoData(SGuid.Parse(text)) : null); Inventory val2 = ((val == null) ? null : ((slot == Slot.Inventory) ? val.Inventory : val.CraftInventory)); if (((val2 != null) ? val2.Data : null) == null) { CoopLog.Debug($"Container {text} ({slot}) isn't in this world."); return; } try { List<Item> list = SerializationUtility.DeserializeValue<List<Item>>(array, (DataFormat)0, (DeserializationContext)null) ?? new List<Item>(); Replace(val2, list, ((ObjectLinkedToDefinition<WGODef>)(object)val).id); signatures[Key(val, slot)] = Signature(Items(val, slot)); Applied++; CoopLog.Debug(string.Format("Updated {0} ({1}) from {2}: {3} stacks.", ((ObjectLinkedToDefinition<WGODef>)(object)val).id, slot, (CoopSession.Role == CoopRole.Host) ? $"client {sender}" : "host", list.Count)); if (CoopSession.Role == CoopRole.Host) { Send(val, slot, Items(val, slot), null, sender); } } catch (Exception e) { CoopLog.Error("Applying the contents of " + ((ObjectLinkedToDefinition<WGODef>)(object)val).id + " failed", e); } } public static List<Item> TakeChangedInventory(WgoData data) { List<Item> list = ((((data != null) ? data.UniqueId : null) != (SGuid)null) ? Items(data, Slot.Inventory) : null); if (list == null) { return null; } string key = Key(data, Slot.Inventory); int num = Signature(list); int value; bool num2 = signatures.TryGetValue(key, out value); signatures[key] = num; if (!num2 || value != num) { return list; } return null; } public static void ApplyInventory(WgoData data, List<Item> items) { Inventory val = ((data != null) ? data.Inventory : null); if (((val != null) ? val.Data : null) != null) { Replace(val, items, ((ObjectLinkedToDefinition<WGODef>)(object)data).id); signatures[Key(data, Slot.Inventory)] = Signature(Items(data, Slot.Inventory)); } } private static void Replace(Inventory inventory, List<Item> items, string what) { List<Item> list = inventory.Data.RemoveAllItems() ?? new List<Item>(); if (items != null && items.Count > 0) { inventory.Data.AddItemsToInventory(items); } bool num = CoopSession.Role == CoopRole.Client; bool applyingRemote = CraftSync.ApplyingRemote; if (num) { CraftSync.ApplyingRemote = true; } try { if (list.Count > 0) { inventory.NotifyItemsRemoved(list); } inventory.NotifyItemsAdded(items ?? new List<Item>()); } catch (Exception ex) { CoopLog.Debug("Redrawing " + what + "'s contents failed: " + ex.Message); } finally { CraftSync.ApplyingRemote = applyingRemote; } } public static string Describe() { return $"tracked={signatures.Count} sent={Sent} applied={Applied}"; } } internal static class ConveyorSync { private struct Moving { public bool Has; public int Direction; public string ItemId; public bool IsCommon; } private const byte OpStep = 1; private const byte OpDump = 2; private static readonly FieldInfo UpdatedEventField = AccessTools.Field(typeof(ConveyorSystem), "OnUpdated"); public static bool ApplyingRemote; public static int StepsSent; public static int StepsApplied; public static int Dumps; public static void Reset() { ApplyingRemote = false; StepsSent = 0; StepsApplied = 0; Dumps = 0; } public static void Tick() { } public static void OnClientReady(ulong clientId) { } public static bool IsBelt(WgoData data) { WgoData obj = ((data is ConveyorWgoData) ? data : null); ConveyorComponent val = ((obj != null) ? ((ConveyorWgoData)obj).ConveyorComponent : null); if (!(val is ConveyorCellComponent) && !(val is ConveyorCellUndergroundComponent) && !(val is ConveyorCellStationComponent)) { return val is ConveyorSplitterComponent; } return true; } private static Moving Read(ConveyorMovableItemData item) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected I4, but got Unknown if (item != null) { return new Moving { Has = true, Direction = (int)item.direction, ItemId = (item.itemId ?? ""), IsCommon = item.isCommon }; } return default(Moving); } public unsafe static void OnHostStep() { //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00fb: Unknown result type (might be due to invalid IL or missing references) if (CoopSession.Role != CoopRole.Host || !CoopSession.HasReadyClients || !CoopSession.IsInGame || !Plugin.HostRunsWorld.Value) { return; } List<ConveyorComponent> list = MainGame.Instance.GameSave?.conveyorSystemData?.conveyorComponents; if (list == null || list.Count == 0) { return; } HashSet<string> scenes = NpcSync.ScenesWithPartners(); List<ConveyorComponent> list2 = list.Where(delegate(ConveyorComponent c) { object obj; if (c == null) { obj = null; } else { ConveyorWgoData wgoData2 = c.WgoData; obj = ((wgoData2 != null) ? ((WgoData)wgoData2).UniqueId : null); } return (SGuid)obj != (SGuid)null && scenes.Contains(((WgoData)c.WgoData).WorldId); }).ToList(); if (list2.Count == 0) { return; } for (int num = 0; num < list2.Count; num += 60) { List<ConveyorComponent> list3 = list2.Skip(num).Take(60).ToList(); FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 1; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); b = ((num + 60 >= list2.Count) ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); int count = list3.Count; ((FastBufferWriter)(ref writer)).WriteValueSafe<int>(ref count, default(ForPrimitives)); foreach (ConveyorComponent item in list3) { ConveyorWgoData wgoData = item.WgoData; CoopMessages.WriteString(ref writer, ((WgoData)wgoData).UniqueId.Id); WriteMoving(ref writer, Read(item.InItem)); WriteMoving(ref writer, Read(item.OutItem)); byte[] array = null; List<Item> list4 = ContainerSync.TakeChangedInventory((WgoData)(object)wgoData); if (list4 != null) { try { array = SerializationUtility.SerializeValue<List<Item>>(list4, (DataFormat)0, (SerializationContext)null); } catch (Exception ex) { CoopLog.Warn("Couldn't send what " + ((ObjectLinkedToDefinition<WGODef>)(object)wgoData).id + " holds: " + ex.Message); } } b = ((array != null) ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); if (array != null) { CoopMessages.WriteBytes(ref writer, array); } } CoopMessages.SendToReadyClients("GK2Coop.Conveyors", writer, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } StepsSent++; } private static void WriteMoving(ref FastBufferWriter w, Moving moving) { //IL_0010: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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) byte b = (moving.Has ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); if (moving.Has) { ((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref moving.Direction, default(ForPrimitives)); CoopMessages.WriteString(ref w, moving.ItemId); b = (moving.IsCommon ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); } } private static ConveyorMovableItemData ReadMoving(ref FastBufferReader reader) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); if (b == 0) { return null; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); string text = CoopMessages.ReadString(ref reader); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b2, default(ForPrimitives)); return new ConveyorMovableItemData(text, (Direction)num, b2 != 0); } private static void ApplyStep(ref FastBufferReader reader) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); byte b2 = default(byte); for (int i = 0; i < num; i++) { string text = CoopMessages.ReadString(ref reader); ConveyorMovableItemData inItem = ReadMoving(ref reader); ConveyorMovableItemData outItem = ReadMoving(ref reader); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b2, default(ForPrimitives)); byte[] array = ((b2 != 0) ? CoopMessages.ReadBytes(ref reader) : null); WorldData worldData = MainGame.WorldData; WgoData obj = ((worldData != null) ? worldData.GetWgoData(SGuid.Parse(text)) : null); ConveyorWgoData val = (ConveyorWgoData)(object)((obj is ConveyorWgoData) ? obj : null); ConveyorComponent val2 = ((val != null) ? val.ConveyorComponent : null); if (val2 == null) { continue; } val2.InItem = inItem; val2.OutItem = outItem; if (array != null) { try { ContainerSync.ApplyInventory((WgoData)(object)val, SerializationUtility.DeserializeValue<List<Item>>(array, (DataFormat)0, (DeserializationContext)null)); } catch (Exception ex) { CoopLog.Warn("Couldn't apply what " + ((ObjectLinkedToDefinition<WGODef>)(object)val).id + " holds: " + ex.Message); } } } if (b == 0) { return; } ApplyingRemote = true; try { ConveyorSystem conveyorSystem = MainGame.Instance.conveyorSystem; (UpdatedEventField?.GetValue(conveyorSystem) as Action)?.Invoke(); LazySingleton<ConveyorSystemAnimationOrchestrator>.Instance.SetState("Out"); ConveyorSoundSystem instance = LazySingleton<ConveyorSoundSystem>.Instance; instance.PauseSounds(); instance.PlaySounds(); StepsApplied++; } catch (Exception e) { CoopLog.Error("Playing the conveyor step failed", e); } finally { ApplyingRemote = false; } } public static void OnLocalDump(Item item, RiverBodyReceiver receiver, Vector3 throwStartPos) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (ApplyingRemote || item == null || (Object)(object)receiver == (Object)null) { return; } Wgo wgo = receiver.Wgo; object obj; if (wgo == null) { obj = null; } else { WgoData data = wgo.Data; obj = ((data != null) ? data.UniqueId : null); } if (!((SGuid)obj == (SGuid)null)) { bool num = CoopSession.Role == CoopRole.Host && CoopSession.HasReadyClients; bool flag = CoopSession.Role == CoopRole.Client && CoopSession.ClientInWorld; if (num || flag) { SendDump(item, receiver.Wgo.Data.UniqueId.Id, throwStartPos, null); CoopLog.Info("Dumped " + ((ObjectLinkedToDefinition<ItemDef>)(object)item).id + " in the river at " + ((ObjectLinkedToDefinition<WGODef>)(object)receiver.Wgo.Data).id + "; mirrored."); } } } private unsafe static void SendDump(Item item, string receiverUid, Vector3 throwStartPos, ulong? except) { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) byte[] bytes; try { bytes = SerializationUtility.SerializeValue<Item>(item, (DataFormat)0, (SerializationContext)null); } catch (Exception e) { CoopLog.Error("Serializing the dumped " + ((ObjectLinkedToDefinition<ItemDef>)(object)item).id + " failed", e); return; } FastBufferWriter val = CoopMessages.NewWriter(); try { FastBufferWriter writer = val; byte b = 2; ((FastBufferWriter)(ref writer)).WriteValueSafe<byte>(ref b, default(ForPrimitives)); CoopMessages.WriteString(ref writer, receiverUid); CoopMessages.WriteVector3(ref writer, throwStartPos); CoopMessages.WriteBytes(ref writer, bytes); if (CoopSession.Role == CoopRole.Host) { CoopMessages.SendToReadyClients("GK2Coop.Conveyors", writer, (NetworkDelivery)4, except); } else { CoopMessages.SendToHost("GK2Coop.Conveyors", writer, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void ApplyDump(ulong sender, ref FastBufferReader reader) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) string text = CoopMessages.ReadString(ref reader); Vector3 val = CoopMessages.ReadVector3(ref reader); Item val2 = SerializationUtility.DeserializeValue<Item>(CoopMessages.ReadBytes(ref reader), (DataFormat)0, (DeserializationContext)null); if (val2 == null) { return; } if (CoopSession.Role == CoopRole.Host) { MainGame.PlayerData.SubRes("cur_bodies_count", 1f); SendDump(val2, text, val, sender); CoopLog.Info((PlayerSync.Get(sender)?.Label ?? sender.ToString()) + " dumped " + ((ObjectLinkedToDefinition<ItemDef>)(object)val2).id + " in the river."); } Wgo wgoViewGlobal = GameScene.GetWgoViewGlobal(SGuid.Parse(text)); RiverBodyReceiver val3 = (((Object)(object)wgoViewGlobal != (Object)null) ? wgoViewGlobal.RiverBodyReceiver : null); if ((Object)(object)val3 == (Object)null) { return; } ApplyingRemote = true; try { MainGame.Instance.riverDropSystem.BeginDump(val2, val3, val); Dumps++; } finally { ApplyingRemote = false; } } public static void OnConveyors(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref b, default(ForPrimitives)); if (CoopSession.Role != CoopRole.Client || CoopSession.ClientInWorld) { if (b == 1 && CoopSession.Role == CoopRole.Client) { ApplyStep(ref reader); } else if (b == 2) { ApplyDump(sender, ref reader); } } } public static string Describe() { if (CoopSession.Role != CoopRole.Host) { return $"steps applied={StepsApplied} dumps={Dumps}"; } return $"steps sent={StepsSent} dumps={Dumps}"; } } [HarmonyPatch(typeof(ConveyorSystemAnimationOrchestrator), "SetState")] internal static class MirrorConveyorStep { private static void Postfix(string name) { if (name != "Out" || ConveyorSync.ApplyingRemote) { return; } try { ConveyorSync.OnHostStep(); } catch (Exception e) { CoopLog.Error("Sending the conveyor step failed", e); } } } [HarmonyPatch(typeof(RiverDropSystem), "BeginDump")] internal static class MirrorRiverDump { private static void Postfix(bool __result, Item item, RiverBodyReceiver receiver, Vector3 throwStartPos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!__result) { return; } try { ConveyorSync.OnLocalDump(item, receiver, throwStartPos); } catch (Exception e) { CoopLog.Error("Mirroring the river dump failed", e); } } } internal static class CoopLog { [CompilerGenerated] private static class <>O { public static LogCallback <0>__OnUnityLog; } private const int KeepFiles = 12; private static StreamWriter writer; private static readonly Dictionary<string, int> sent = new Dictionary<string, int>(); private static readonly Dictionary<string, int> received = new Dictionary<string, int>(); private static readonly Dictionary<string, int> repeatedErrors = new Dictionary<string, int>(); public static string FilePath { get; private set; } public static bool Verbose { get { if (Plugin.VerboseLogging != null) { return Plugin.VerboseLogging.Value; } return true; } } public static void Init() { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown try { string text = Path.Combine(Paths.BepInExRootPath, "GK2Coop-logs"); Directory.CreateDirectory(text); foreach (FileInfo item in (from f in new DirectoryInfo(text).GetFiles("coop_*.log") orderby f.CreationTimeUtc descending select f).Skip(11)) { try { item.Delete(); } catch { } } FilePath = Path.Combine(text, $"coop_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_pid{Process.GetCurrentProcess().Id}.log"); writer = new StreamWriter(new FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)) { AutoFlush = true }; writer.WriteLine(string.Format("GK2 Co-op {0} debug log. Game folder: {1} pid {2}", "0.27.0", Path.GetDirectoryName(Application.dataPath), Process.GetCurrentProcess().Id)); object obj2 = <>O.<0>__OnUnityLog; if (obj2 == null) { LogCallback val = OnUnityLog; <>O.<0>__OnUnityLog = val; obj2 = (object)val; } Application.logMessageReceived += (LogCallback)obj2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't create the co-op debug log: " + ex.Message)); } } public static void Info(string message) { Write("INFO ", message); Plugin.Log.LogInfo((object)message); } public static void Warn(string message) { Write("WARN ", message); Plugin.Log.LogWarning((object)message); } public static void Error(string message, Exception e = null) { Write("ERROR", (e == null) ? message : $"{message}: {e}"); Plugin.Log.LogError((object)((e == null) ? message : $"{message}: {e}")); } public static void Debug(string message) { if (Verbose) { Write("DEBUG", message); } } public static void CountSent(string channel, int bytes) { Bump(sent, channel); } public static void CountReceived(string channel, int bytes) { Bump(received, channel); } public static string Counters() { return "sent[" + Format(sent) + "] recv[" + Format(received) + "]"; static string Format(Dictionary<string, int> d) { if (d.Count != 0) { return string.Join(" ", from p in d orderby p.Key select $"{p.Key}={p.Value}"); } return "-"; } } public static void ResetCounters() { sent.Clear(); received.Clear(); } private static void Bump(Dictionary<string, int> counts, string key) { counts.TryGetValue(key, out var value); counts[key] = value + 1; } private static void OnUnityLog(string condition, string stackTrace, LogType type) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_003d: 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_0010: Invalid comparison between Unknown and I4 if (CoopSession.Role != CoopRole.None && ((int)type == 0 || (int)type == 4 || (int)type == 1)) { repeatedErrors.TryGetValue(condition, out var value); repeatedErrors[condition] = value + 1; if (value < 3) { Write("UNITY", $"{type}: {condition}\n{stackTrace}".TrimEnd()); } else if (value == 3) { Write("UNITY", "(further repeats of this error are counted, not logged) " + condition); } } } private static void Write(string level, string message) { if (writer == null) { return; } try { string text = ((CoopSession.Role == CoopRole.None) ? "----" : CoopSession.Role.ToString().ToUpperInvariant()); writer.WriteLine($"{DateTime.Now:HH:mm:ss.fff} f{Time.frameCount,-7} {text,-6} {level} {message}"); } catch { } } } internal static class CoopMessages { public const string PlayerState = "GK2Coop.State"; public const string PlayerInfo = "GK2Coop.Info"; public const string Time = "GK2Coop.Time"; public const string Story = "GK2Coop.Story"; public const string World = "GK2Coop.World"; public const string Request = "GK2Coop.Request"; public const string Npc = "GK2Coop.Npc"; public const string Drops = "GK2Coop.Drops"; public const string Economy = "GK2Coop.Economy"; public const string Knowledge = "GK2Coop.Knowledge"; public const string Containers = "GK2Coop.Containers"; public const string Sleep = "GK2Coop.Sleep"; public const string WorldState = "GK2Coop.WorldState"; public const string Vendors = "GK2Coop.Vendors"; public const string Effects = "GK2Coop.Effects"; public const string Crafts = "GK2Coop.Crafts"; public const string Locks = "GK2Coop.Locks"; public const string Combat = "GK2Coop.Combat"; public const string Conveyors = "GK2Coop.Conveyors"; public const string Progress = "GK2Coop.Progress"; public const string Zombies = "GK2Coop.Zombies"; public const string Director = "GK2Coop.Director"; public const string Tutorial = "GK2Coop.Tutorial"; public const string Travel = "GK2Coop.Travel"; public const string Troops = "GK2Coop.Troops"; public const string ItemScripts = "GK2Coop.ItemScripts"; public const string Sermons = "GK2Coop.Sermons"; private static readonly Dictionary<string, Action<ulong, FastBufferReader>> handlers = new Dictionary<string, Action<ulong, FastBufferReader>> { { "GK2Coop.State", PlayerSync.OnState }, { "GK2Coop.Info", PlayerSync.OnInfo }, { "GK2Coop.Time", TimeSync.OnTime }, { "GK2Coop.Story", StorySync.OnStory }, { "GK2Coop.World", WorldSync.OnWorld }, { "GK2Coop.Request", StorySync.OnRequest }, { "GK2Coop.Npc", NpcSync.OnNpc }, { "GK2Coop.Drops", DropSync.OnDrops }, { "GK2Coop.Economy", EconomySync.OnEconomy }, { "GK2Coop.Knowledge", KnowledgeSync.OnKnowledge }, { "GK2Coop.Containers", ContainerSync.OnContainers }, { "GK2Coop.Sleep", SleepSync.OnSleep }, { "GK2Coop.WorldState", WorldStateSync.OnWorldState }, { "GK2Coop.Vendors", VendorSync.OnVendors }, { "GK2Coop.Effects", EffectSync.OnEffects }, { "GK2Coop.Crafts", CraftSync.OnCrafts }, { "GK2Coop.Locks", ChestLocks.OnLocks }, { "GK2Coop.Combat", CombatSync.OnCombat }, { "GK2Coop.Conveyors", ConveyorSync.OnConveyors }, { "GK2Coop.Progress", ProgressSync.OnProgress }, { "GK2Coop.Zombies", InteractionProxy.OnZombies }, { "GK2Coop.Troops", TroopSync.OnTroops }, { "GK2Coop.ItemScripts", GK2Coop.ItemScripts.OnItemScripts }, { "GK2Coop.Sermons", SermonSync.OnSermons }, { "GK2Coop.Director", StandIn.OnDirector }, { "GK2Coop.Tutorial", TutorialSync.OnTutorial }, { "GK2Coop.Travel", SceneWait.OnTravel }, { "GK2Coop.Profile", PartnerProfiles.OnMessage } }; public static void Register() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; foreach (KeyValuePair<string, Action<ulong, FastBufferReader>> handler2 in handlers) { string name = handler2.Key; Action<ulong, FastBufferReader> handler = handler2.Value; customMessagingManager.RegisterNamedMessageHandler(name, (HandleNamedMessageDelegate)delegate(ulong sender, FastBufferReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) CoopLog.CountReceived(Short(name), ((FastBufferReader)(ref reader)).Length); try { handler(sender, reader); } catch (Exception e) { CoopLog.Error($"Handling {name} from {sender} failed", e); } }); } } public static FastBufferWriter NewWriter() { //IL_000b: Unknown result type (might be due to invalid IL or missing references)