Decompiled source of CardShopCoop v1.0.6
CardShopCoop.dll
Decompiled 2 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.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CC; using CardShopCoop.Net; using CardShopCoop.Patches; using CardShopCoop.Sync; using CardShopCoop.UI; using CardShopCoop.Util; using HarmonyLib; using Steamworks; using TMPro; using UnityEngine; 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("CardShopCoop")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.8.0.0")] [assembly: AssemblyInformationalVersion("0.8.0+7fe1bd680ed79bbda02583aeb3494b610d84fb83")] [assembly: AssemblyProduct("CardShopCoop")] [assembly: AssemblyTitle("CardShopCoop")] [assembly: AssemblyVersion("0.8.0.0")] namespace CardShopCoop { public enum CoopRole { None, Host, Client } public class CoopCore : MonoBehaviour { private struct PendingCard { public bool IsAdd; public int Amount; public CardData Card; } public string StatusLine = "Not connected"; public string ErrorLine = ""; public string HostTimeLine = ""; public string RegisterLine = ""; public float RegisterLineTimer; private float _serveThrottle; public readonly Dictionary<int, string> PeerNames = new Dictionary<int, string>(); private ICoopTransport _net; private readonly SteamLobby _steamLobby = new SteamLobby(); private ulong _autoJoinSteamLobby; private readonly AvatarManager _avatars = new AvatarManager(); private readonly WorldSync _world = new WorldSync(); private readonly NpcSync _npcs = new NpcSync(); private readonly CardShelfSync _cardShelves = new CardShelfSync(); private readonly ObjMoveSync _objMoves = new ObjMoveSync(); private readonly BoxSync _boxes = new BoxSync(); private readonly PopulationSync _population = new PopulationSync(); private readonly GradingSync _grading = new GradingSync(); private readonly TradeServe _trades = new TradeServe(); private readonly PlayTableSync _tables = new PlayTableSync(); private readonly StaffSync _staff = new StaffSync(); private readonly ShopStateSync _shopState = new ShopStateSync(); private readonly SettingsSync _settings = new SettingsSync(); private readonly MarketSync _market = new MarketSync(); private readonly ReportSync _report = new ReportSync(); private readonly ContainerSync _containers = new ContainerSync(); private readonly TournamentSync _tournament = new TournamentSync(); private readonly CardBoxSync _cardBoxes = new CardBoxSync(); private string _lastShopNameSent; private float _shopNameTimer = -1f; private readonly RegisterMirror _registerMirror = new RegisterMirror(); private float _npcSweepTimer = -1.3f; private float _regStateTimer = -0.17f; public string PromptLine = ""; private readonly ConcurrentQueue<Action> _mainThread = new ConcurrentQueue<Action>(); private CoopUI _ui; private MemoryStream _saveBuf; private int _saveExpected = -1; private byte[] _pendingSave; private MemoryStream _bundleBuf; private int _bundleExpected = -1; private int _hostSlot; private bool _worldRequested; private float _priceTimer = -0.45f; private int _lastPriceHash; private float _stateTimer; private float _pingTimer; private float _econTimer = -0.11f; private float _dayTimer = -0.9f; private Vector3 _lastPos; private bool _hasLastPos; private double _lastCoinSent = double.MinValue; private long _lastProgressSent = long.MinValue; private readonly HashSet<int> _gotStateFrom = new HashSet<int>(); private bool _loggedEconLink; private bool _loggedTimeLink; private long _diagSent; private long _diagRecvStates; private float _diagTimer = -7.3f; private float _errLogCooldown; private static readonly FieldInfo FiTimeHour = typeof(LightManager).GetField("m_TimeHour", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo FiTimeMin = typeof(LightManager).GetField("m_TimeMin", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo FiTimeMinFloat = typeof(LightManager).GetField("m_TimeMinFloat", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo FiHasDayEnded = typeof(LightManager).GetField("m_HasDayEnded", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo MiDayReset = typeof(LightManager).GetMethod("DelayUpdateEnv", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo FiTimeOfDayIdx = typeof(LightManager).GetField("m_TImeOfDayIndex", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo FiFinishLoading = typeof(LightManager).GetField("m_FinishLoading", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo MiLightInit = typeof(LightManager).GetMethod("Init", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo MiUpdateLightData = typeof(LightManager).GetMethod("UpdateLightTimeData", BindingFlags.Instance | BindingFlags.NonPublic); private float _lightSyncTimer = -2.3f; private LightManager _lightManager; private float _cardResyncTimer = -5.2f; private float _licenseSyncTimer = -3.7f; private double _lastLicenseBuyTime = -999.0; private string _lastLightJson; private float _lightHeal; private int _lastLicenseHash; private float _licenseHeal; private float _dt; private bool _syncActive; private Action _actNetPump; private Action _actAvatars; private Action _actWorld; private Action _actCardShelves; private Action _actObjMoves; private Action _actBoxes; private Action _actPopulation; private Action _actNpcPuppets; private Action _actRegisterMirror; private Action _actNpcSweep; private Action _actStateSend; private Action _actNpcCollect; private Action _actRegisterCollect; private Action _actModules; private CustomerManager _cmSweep; private bool _renamerHandled; private int _heldBoxFrame = -1; private object _heldBoxA; private object _heldBoxB; private object _heldBoxC; private readonly List<InMsg> _dispatchBuf = new List<InMsg>(64); private readonly HashSet<long> _dispatchSeen = new HashSet<long>(); private int _autoHostSlot = -1; private string _autoJoinIp; private int _autoPhase; private float _autoTimer; public string HostPassword = ""; private string _joinPassword = ""; public CSteamID LastFailedLobby = CSteamID.Nil; private readonly List<KeyValuePair<int, float>> _pendingKicks = new List<KeyValuePair<int, float>>(); private readonly List<PendingCard> _pendingCardDeltas = new List<PendingCard>(); private readonly List<KeyValuePair<CardData, float>> _pendingCardPrices = new List<KeyValuePair<CardData, float>>(); private int _selfId = -1; private readonly HashSet<int> _relayIds = new HashSet<int>(); private Transform _playerTf; private Transform _playerCamTf; private InteractionPlayerController _playerIpc; private static readonly FieldInfo FiHoldBox = AccessTools.Field(typeof(InteractionPlayerController), "m_CurrentHoldingBox"); private static readonly FieldInfo FiHoldItemBox = AccessTools.Field(typeof(InteractionPlayerController), "m_CurrentHoldingItemBox"); private static readonly FieldInfo FiHoldBoxShelf = AccessTools.Field(typeof(InteractionPlayerController), "m_CurrentHoldingBoxShelf"); private static readonly FieldInfo FiHoldBoxCard = AccessTools.Field(typeof(InteractionPlayerController), "m_CurrentHoldingBoxCard"); private static readonly FieldInfo FiHoldItemList = AccessTools.Field(typeof(InteractionPlayerController), "m_HoldItemList"); private readonly List<int> _holdTypesBuf = new List<int>(6); private readonly List<CardData> _holdCardsBuf = new List<CardData>(4); private static readonly FieldInfo FiHoldCard3dList = AccessTools.Field(typeof(InteractionPlayerController), "m_CurrentHoldingCard3dList"); private static readonly FieldInfo FiViewAlbum = AccessTools.Field(typeof(InteractionPlayerController), "m_IsViewCardAlbumMode"); private static readonly FieldInfo FiPanelIndex = AccessTools.Field(typeof(RestockItemPanelUI), "m_Index"); private static readonly FieldInfo FiPanelLicGrp = AccessTools.Field(typeof(RestockItemPanelUI), "m_LicenseUIGrp"); private static readonly FieldInfo FiPanelUIGrp = AccessTools.Field(typeof(RestockItemPanelUI), "m_UIGrp"); private bool _catalogSent; private float _catalogTimer; private int _lastCatalogSentHash; private readonly Dictionary<int, string> _rosterNames = new Dictionary<int, string>(); private HashSet<int> _clientPriced = new HashSet<int>(); private HashSet<int> _incomingPriced = new HashSet<int>(); public static CoopCore Instance { get; private set; } public static CoopRole Role { get; private set; } = CoopRole.None; public bool IsSteamSession { get; private set; } public SteamLobby Lobby => _steamLobby; private void Guarded(string stage, Action action) { try { action(); } catch (Exception arg) { if (_errLogCooldown <= 0f) { _errLogCooldown = 5f; CoopPlugin.Log.LogError((object)$"[{stage}] {arg}"); } } } private unsafe void Awake() { Instance = this; _ui = new CoopUI(); _world.OnLocalChanges = OnLocalWorldChanges; _cardShelves.OnLocalChanges = delegate(List<CardShelfSync.Entry> changes) { if (Role == CoopRole.Host) { Broadcast(MsgType.CardShelfDelta, delegate(BinaryWriter bw) { CardShelfSync.WriteEntries(bw, changes); }); } else if (Role == CoopRole.Client) { Send(1, MsgType.CardShelfRequest, delegate(BinaryWriter bw) { CardShelfSync.WriteEntries(bw, changes); }); } }; _objMoves.OnLocalChanges = delegate(List<ObjMoveSync.Entry> changes) { if (Role == CoopRole.Host) { Broadcast(MsgType.ObjMoveDelta, delegate(BinaryWriter bw) { ObjMoveSync.WriteEntries(bw, changes); }); } else if (Role == CoopRole.Client) { Send(1, MsgType.ObjMoveRequest, delegate(BinaryWriter bw) { ObjMoveSync.WriteEntries(bw, changes); }); } }; _population.OnHostSnapshot = delegate(List<List<PopulationSync.Entry>> all) { Broadcast(MsgType.PopState, delegate(BinaryWriter bw) { PopulationSync.Write(bw, all); }); }; _boxes.OnHostSnapshot = delegate(List<BoxSync.Entry> list) { Broadcast(MsgType.BoxState, delegate(BinaryWriter bw) { BoxSync.WriteEntries(bw, list); }); }; _boxes.OnClientChanges = delegate(List<BoxSync.Entry> list) { Send(1, MsgType.BoxRequest, delegate(BinaryWriter bw) { BoxSync.WriteEntries(bw, list); }); }; BoxSync.IsLocallyCarried = delegate(InteractablePackagingBox_Item box) { if ((Object)(object)_playerIpc == (Object)null || (Object)(object)box == (Object)null) { return false; } try { if (_heldBoxFrame != Time.frameCount) { _heldBoxFrame = Time.frameCount; _heldBoxA = FiHoldItemBox?.GetValue(_playerIpc); _heldBoxB = FiHoldBox?.GetValue(_playerIpc); _heldBoxC = FiHoldBoxCard?.GetValue(_playerIpc); } return _heldBoxA == box || _heldBoxB == box; } catch { return false; } }; CardBoxSync.IsLocallyCarried = delegate(InteractablePackagingBox_Card box) { if ((Object)(object)_playerIpc == (Object)null || (Object)(object)box == (Object)null) { return false; } try { if (_heldBoxFrame != Time.frameCount) { _heldBoxFrame = Time.frameCount; _heldBoxA = FiHoldItemBox?.GetValue(_playerIpc); _heldBoxB = FiHoldBox?.GetValue(_playerIpc); _heldBoxC = FiHoldBoxCard?.GetValue(_playerIpc); } return _heldBoxC == box || _heldBoxB == box; } catch { return false; } }; BoxSync.LocalBoxDestroyed = delegate(InteractablePackagingBox_Item box) { if (InGameLevel()) { if (Role == CoopRole.Client) { _boxes.NotifyLocalDestroyed(box); } else if (Role == CoopRole.Host) { _boxes.HostNotifyLocalDestroyed(); } } }; _boxes.OnLocalRemoved = delegate(int idx, int type) { Send(1, MsgType.BoxRemoved, delegate(BinaryWriter bw) { bw.Write(idx); bw.Write(type); }); }; PopulationSync.OnClientStructureChanged = delegate(int kind) { if (Role == CoopRole.Client && (kind == 2 || kind == 3)) { _cardShelves.InvalidateBaseline(); } }; _actNetPump = delegate { _net.PumpMainThread(); }; _actAvatars = delegate { AvatarManager.ViewCamera = _playerCamTf; _avatars.Tick(_dt); }; _actWorld = delegate { _world.Tick(_dt, _syncActive); }; _actCardShelves = delegate { _cardShelves.IsClientRole = Role == CoopRole.Client; _cardShelves.Tick(_dt, _syncActive); }; _actObjMoves = delegate { _objMoves.Tick(_dt, _syncActive); }; _actBoxes = delegate { if (Role == CoopRole.Host) { _boxes.HostTick(_dt, _syncActive); } else if (Role == CoopRole.Client) { _boxes.ClientTick(_dt, _syncActive); } }; _actPopulation = delegate { if (Role == CoopRole.Host) { _population.HostTick(_dt, _syncActive); } }; _actNpcPuppets = delegate { _npcs.TickPuppets(_dt, InGameLevel()); }; _actRegisterMirror = RegisterMirrorTick; _actNpcSweep = NpcSweepTick; _actStateSend = StateSendTick; _actNpcCollect = NpcCollectTick; _actRegisterCollect = RegisterCollectTick; _grading.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.GradingOp, w); }; _grading.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.GradingState, w); }; _trades.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.TradeOp, w); }; _trades.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.TradeState, w); }; _tables.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.TableState, w); }; _staff.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.StaffOp, w); }; _staff.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.StaffState, w); }; _shopState.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.ShopOp, w); }; _shopState.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.ShopState, w); }; _settings.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.SettingsOp, w); }; _settings.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.SettingsState, w); }; _market.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.MarketState, w); }; _report.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.ReportState, w); }; _containers.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.ContainerOp, w); }; _containers.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.ContainerState, w); }; _tournament.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.TournamentState, w); }; _cardBoxes.SendOp = delegate(Action<BinaryWriter> w) { Send(1, MsgType.CardBoxOp, w); }; _cardBoxes.BroadcastState = delegate(Action<BinaryWriter> w) { Broadcast(MsgType.CardBoxState, w); }; _actModules = ModulesTick; SceneManager.sceneLoaded += OnSceneLoaded; string[] commandLineArgs = Environment.GetCommandLineArgs(); for (int num = 0; num < commandLineArgs.Length; num++) { string text = commandLineArgs[num]; ulong result2; if (text.StartsWith("-coopautohost=") && int.TryParse(text.Substring(14), out var result)) { _autoHostSlot = result; } else if (text.StartsWith("-coopautojoin=")) { _autoJoinIp = text.Substring(14); } else if (text == "+connect_lobby" && num + 1 < commandLineArgs.Length && ulong.TryParse(commandLineArgs[num + 1], out result2)) { _autoJoinSteamLobby = result2; } } if (_autoHostSlot >= 0) { CoopPlugin.Log.LogInfo((object)$"AUTO: will load slot {_autoHostSlot} and host"); } if (_autoJoinIp != null) { CoopPlugin.Log.LogInfo((object)("AUTO: will join " + _autoJoinIp)); } if (_autoJoinSteamLobby != 0L) { CoopPlugin.Log.LogInfo((object)$"AUTO: will join Steam lobby {_autoJoinSteamLobby}"); } _steamLobby.Init(); _steamLobby.OnError = delegate(string err) { ErrorLine = err; CoopPlugin.Log.LogWarning((object)err); }; _steamLobby.OnLobbyCreated = delegate(CSteamID lobby) { //IL_002b: 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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (_net is SteamTransport steamTransport) { steamTransport.LobbyId = lobby; } StatusLine = "Hosting via Steam - click 'Invite friend'"; ManualLogSource log = CoopPlugin.Log; CSteamID val = lobby; log.LogInfo((object)("steam: lobby live " + ((object)(*(CSteamID*)(&val))/*cast due to .constrained prefix*/).ToString())); }; _steamLobby.OnEnteredLobby = delegate(CSteamID owner) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Role == CoopRole.Client && _net is SteamTransport steamTransport) { steamTransport.LobbyId = _steamLobby.LobbyId; steamTransport.ConnectToHost(owner); StatusLine = "Connected via Steam - requesting world..."; SendHello(); } }; _steamLobby.OnInviteAccepted = delegate(CSteamID lobby) { //IL_000a: 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_0024: Unknown result type (might be due to invalid IL or missing references) ManualLogSource log = CoopPlugin.Log; CSteamID val = lobby; log.LogInfo((object)("steam: invite accepted -> lobby " + ((object)(*(CSteamID*)(&val))/*cast due to .constrained prefix*/).ToString())); JoinSteam(lobby); }; CEventManager.AddListener<CEventPlayer_OnOpenCardPack>((EventDelegate<CEventPlayer_OnOpenCardPack>)OnLocalPackOpened); } public void JoinSteam(CSteamID lobby, string password = "") { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) ErrorLine = ""; if (Role != CoopRole.None) { ErrorLine = "Already in a session."; return; } if (InGameLevel()) { ErrorLine = "Go to the main menu first, then accept the invite again."; return; } if (!_steamLobby.SteamAvailable()) { ErrorLine = "Steam isn't running."; return; } Role = CoopRole.Client; IsSteamSession = true; _joinPassword = password ?? ""; LastFailedLobby = lobby; _net = new SteamTransport(isHost: false) { KeepaliveFrame = Msg.Build(MsgType.Ping) }; StatusLine = "Joining Steam lobby..."; _steamLobby.Join(lobby); } public void StartHostingSteam(bool isPublic, string lobbyName, string password) { ErrorLine = ""; if (Role != CoopRole.None) { ErrorLine = "Already in a session."; return; } if (!InGameLevel()) { ErrorLine = "Load your shop first, then host."; return; } if (!_steamLobby.SteamAvailable()) { ErrorLine = "Steam isn't running - use LAN instead."; return; } Role = CoopRole.Host; IsSteamSession = true; HostPassword = password ?? ""; _net = new SteamTransport(isHost: true) { KeepaliveFrame = Msg.Build(MsgType.Ping) }; StatusLine = "Creating Steam lobby..."; _steamLobby.Host(isPublic, lobbyName, HostPassword.Length > 0); } public void OpenSteamInvite() { _steamLobby.OpenInviteDialog(); } private void SendHello() { Send(1, MsgType.Hello, delegate(BinaryWriter bw) { bw.Write("1.0.6"); bw.Write(CoopPlugin.PlayerName.Value); bw.Write(_joinPassword ?? ""); bw.Write(ModParity.PluginHash()); bw.Write(ModParity.EnumHash()); }); } private void RejectConn(int connId, string reason) { CoopPlugin.Log.LogWarning((object)$"rejected connection {connId}: {reason}"); Send(connId, MsgType.Bye, delegate(BinaryWriter bw) { bw.Write(reason); }); _pendingKicks.Add(new KeyValuePair<int, float>(connId, 1.5f)); } private static void ReadHoldPayload(BinaryReader br, byte hold, out List<int> types, out List<CardData> cards) { types = null; cards = null; int num = br.ReadByte(); if (num == 0) { return; } if (hold == 3) { cards = new List<CardData>(num); for (int i = 0; i < num; i++) { cards.Add(Msg.ReadCard(br)); } } else { types = new List<int>(num); for (int j = 0; j < num; j++) { types.Add(br.ReadInt32()); } } } private static void WriteHoldPayload(BinaryWriter bw, byte hold, List<int> types, List<CardData> cards) { if (hold == 3) { bw.Write((byte)(cards?.Count ?? 0)); if (cards == null) { return; } { foreach (CardData card in cards) { Msg.WriteCard(bw, card); } return; } } bw.Write((byte)(types?.Count ?? 0)); if (types == null) { return; } foreach (int type in types) { bw.Write(type); } } private static void ApplyCardDelta(bool isAdd, int amount, CardData card) { GamePatches.ApplyingRemoteCards = true; try { if (isAdd) { CPlayerData.AddCard(card, amount); } else { CPlayerData.ReduceCard(card, amount); } } finally { GamePatches.ApplyingRemoteCards = false; } } private void FlushPendingCardWork() { if (!InGameLevel() || (_pendingCardDeltas.Count == 0 && _pendingCardPrices.Count == 0)) { return; } Guarded("pending-cards", delegate { foreach (PendingCard pendingCardDelta in _pendingCardDeltas) { ApplyCardDelta(pendingCardDelta.IsAdd, pendingCardDelta.Amount, pendingCardDelta.Card); } if (_pendingCardDeltas.Count > 0) { CoopPlugin.Log.LogInfo((object)$"applied {_pendingCardDeltas.Count} card change(s) held during loading"); } _pendingCardDeltas.Clear(); GamePatches.ApplyingRemotePrice = true; try { foreach (KeyValuePair<CardData, float> pendingCardPrice in _pendingCardPrices) { CPlayerData.SetCardPrice(pendingCardPrice.Key, pendingCardPrice.Value); } } finally { GamePatches.ApplyingRemotePrice = false; } _pendingCardPrices.Clear(); }); } private void RelayTagToOthers(int senderConn, byte kind, int extra = -1) { if (Role != CoopRole.Host || _net == null || _net.ConnectionCount <= 1) { return; } byte[] frame = Msg.Build(MsgType.RelayTag, delegate(BinaryWriter bw) { bw.Write((byte)senderConn); bw.Write(kind); bw.Write(extra); }); foreach (int item in _net.ConnIds()) { if (item != senderConn) { _net.Send(item, frame); } } } private void BroadcastRoster() { if (Role != CoopRole.Host) { return; } List<KeyValuePair<int, string>> entries = new List<KeyValuePair<int, string>>(PeerNames); Broadcast(MsgType.Roster, delegate(BinaryWriter bw) { bw.Write((byte)entries.Count); foreach (KeyValuePair<int, string> item in entries) { bw.Write((byte)item.Key); bw.Write(item.Value); } }); } private void OnLocalPackOpened(CEventPlayer_OnOpenCardPack evt) { if (Role != CoopRole.None && _net != null && _net.ConnectionCount > 0) { Broadcast(MsgType.Activity, delegate(BinaryWriter bw) { bw.Write((byte)1); bw.Write(evt.m_PackIndex); }); } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; CEventManager.RemoveListener<CEventPlayer_OnOpenCardPack>((EventDelegate<CEventPlayer_OnOpenCardPack>)OnLocalPackOpened); Shutdown("plugin unloaded"); } private void OnApplicationQuit() { Shutdown("game closed"); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { _avatars.Clear(); _world.Reset(); _npcs.Reset(); _cardShelves.Reset(); _objMoves.Reset(); _boxes.Reset(); _population.Reset(); _registerMirror.Reset(); ModulesReset(); PromptLine = ""; _lightManager = null; _cmSweep = null; _renamerHandled = false; _catalogSent = false; _playerTf = null; _playerCamTf = null; _playerIpc = null; if (((Scene)(ref scene)).name == "Title" && Role == CoopRole.Client && _net != null) { Shutdown("left the session"); } } private bool InGameLevel() { CGameManager instance = CSingleton<CGameManager>.Instance; if ((Object)(object)instance != (Object)null) { return instance.m_IsGameLevel; } return false; } private void ModulesTick() { bool flag = InGameLevel(); if (Role == CoopRole.Host) { _grading.HostTick(_dt, flag); _trades.HostTick(_dt, flag); _tables.HostTick(_dt, flag); _staff.HostTick(_dt, flag); _shopState.HostTick(_dt, flag); _settings.HostTick(_dt, flag); _market.HostTick(_dt, flag); _report.HostTick(_dt, flag); _containers.HostTick(_dt, flag); _tournament.HostTick(_dt, flag); _cardBoxes.HostTick(_dt, flag); } else { if (Role != CoopRole.Client) { return; } _trades.ClientTick(_dt, flag); _cardBoxes.ClientTick(_dt, flag); _catalogTimer += _dt; if (flag && (_catalogTimer >= 45f || !_catalogSent)) { _catalogTimer = 0f; _catalogSent = true; int num = LocalCatalogHash(); if (num != _lastCatalogSentHash) { _lastCatalogSentHash = num; SendCatalogDigest(); } } } } private static int LocalCatalogHash() { //IL_002a: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected I4, but got Unknown try { List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; int num = 17; foreach (RestockData item in restockDataList) { if (item != null) { num = num * 31 + ((item.itemType << 1) | item.isBigBox); } } return num; } catch { return 0; } } private void ModulesReset() { _grading.Reset(); _trades.Reset(); _tables.Reset(); _staff.Reset(); _shopState.Reset(); _settings.Reset(); _market.Reset(); _report.Reset(); _containers.Reset(); _tournament.Reset(); _cardBoxes.Reset(); } private void ModulesForceResend() { _grading.ForceResend(); _trades.ForceResend(); _tables.ForceResend(); _staff.ForceResend(); _shopState.ForceResend(); _settings.ForceResend(); _market.ForceResend(); _report.ForceResend(); _containers.ForceResend(); _tournament.ForceResend(); _cardBoxes.ForceResend(); } private void RegisterMirrorTick() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) _registerMirror.Tick(_dt); _regStateTimer += _dt; if (_regStateTimer >= 0.5f && InGameLevel()) { _regStateTimer -= 0.5f; Transform val = ResolvePlayer(); int nearestCounter = (((Object)(object)val != (Object)null) ? RegisterServe.FindNearestCounter(val.position, CoopPlugin.ServeReach.Value, quiet: true) : (-1)); PromptLine = _registerMirror.PromptFor(nearestCounter) ?? _trades.PromptFor(nearestCounter) ?? ""; } } private void NpcSweepTick() { if (!_renamerHandled) { _renamerHandled = true; ShopRenamer val = Object.FindObjectOfType<ShopRenamer>(); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); CoopPlugin.Log.LogInfo((object)"disabled shop-renamer trigger (host names the shop)"); } } if ((Object)(object)_cmSweep == (Object)null) { _cmSweep = Object.FindObjectOfType<CustomerManager>(); } if ((Object)(object)_cmSweep != (Object)null) { List<Customer> customerList = _cmSweep.GetCustomerList(); for (int i = 0; i < customerList.Count; i++) { if ((Object)(object)customerList[i] != (Object)null && ((Component)customerList[i]).gameObject.activeSelf) { ((Component)customerList[i]).gameObject.SetActive(false); } } } List<Worker> workerList = WorkerManager.GetWorkerList(); if (workerList == null) { return; } for (int j = 0; j < workerList.Count; j++) { if ((Object)(object)workerList[j] != (Object)null && ((Component)workerList[j]).gameObject.activeSelf) { ((Component)workerList[j]).gameObject.SetActive(false); } } } private void StateSendTick() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_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_010a: 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_00e2: Unknown result type (might be due to invalid IL or missing references) float num = 1f / Mathf.Clamp(CoopPlugin.SendRateHz.Value, 4f, 30f); Transform val = (InGameLevel() ? ResolvePlayer() : null); if (_stateTimer < num || (Object)(object)val == (Object)null) { return; } Vector3 pos = val.position; float speed = 0f; if (_hasLastPos) { Vector3 val2 = pos - _lastPos; val2.y = 0f; speed = Mathf.Clamp(((Vector3)(ref val2)).magnitude / _stateTimer, 0f, 6f); } _lastPos = pos; _hasLastPos = true; float yaw = (((Object)(object)_playerCamTf != (Object)null) ? _playerCamTf.eulerAngles.y : (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.eulerAngles.y : val.eulerAngles.y)); byte hold = ComputeHoldState(); BroadcastTransient(MsgType.PlayerState, delegate(BinaryWriter bw) { bw.Write(pos.x); bw.Write(pos.y); bw.Write(pos.z); bw.Write(yaw); bw.Write(speed); bw.Write(hold); if (hold == 3) { bw.Write((byte)_holdCardsBuf.Count); { foreach (CardData item in _holdCardsBuf) { Msg.WriteCard(bw, item); } return; } } bw.Write((byte)_holdTypesBuf.Count); foreach (int item2 in _holdTypesBuf) { bw.Write(item2); } }); _diagSent++; _stateTimer = 0f; } private void NpcCollectTick() { List<byte[]> list = _npcs.HostCollect(_dt); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { byte[] c = list[i]; BroadcastTransient(MsgType.NpcState, delegate(BinaryWriter bw) { bw.Write(c); }); } } private void RegisterCollectTick() { _regStateTimer += _dt; if (!(_regStateTimer >= 0.5f)) { return; } _regStateTimer -= 0.5f; byte[] batch = RegisterServe.CollectStates(); if (batch != null) { BroadcastTransient(MsgType.RegisterState, delegate(BinaryWriter bw) { bw.Write(batch); }); } } private Transform ResolvePlayer() { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_playerTf != (Object)null) { return _playerTf; } InteractionPlayerController val = InteractionPlayerController.m_Instance; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType<InteractionPlayerController>(); } if ((Object)(object)val != (Object)null) { _playerIpc = val; _playerTf = (((Object)(object)val.m_WalkerCtrl != (Object)null) ? ((Component)val.m_WalkerCtrl).transform : ((Component)val).transform); _playerCamTf = (((Object)(object)val.m_Cam != (Object)null) ? ((Component)val.m_Cam).transform : null); CoopPlugin.Log.LogInfo((object)string.Format("Player body resolved: {0} at {1}, cam={2}", ((Object)_playerTf).name, _playerTf.position, ((Object)(object)_playerCamTf != (Object)null) ? ((Object)_playerCamTf).name : "none")); } return _playerTf; } private byte ComputeHoldState() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected I4, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected I4, but got Unknown _holdTypesBuf.Clear(); _holdCardsBuf.Clear(); if ((Object)(object)_playerIpc == (Object)null) { return 0; } try { if (IsAlive(FiHoldBox) || IsAlive(FiHoldItemBox) || IsAlive(FiHoldBoxShelf) || IsAlive(FiHoldBoxCard)) { object? obj = FiHoldItemBox?.GetValue(_playerIpc); InteractablePackagingBox_Item val = (InteractablePackagingBox_Item)((obj is InteractablePackagingBox_Item) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { _holdTypesBuf.Add(val.m_IsBigBox ? 1 : 0); try { _holdTypesBuf.Add((int)val.m_ItemCompartment.GetItemType()); } catch { _holdTypesBuf.Add(0); } } return 1; } if (FiHoldItemList?.GetValue(_playerIpc) is List<Item> { Count: >0 } list) { for (int i = 0; i < list.Count; i++) { if (_holdTypesBuf.Count >= 6) { break; } if ((Object)(object)list[i] != (Object)null) { _holdTypesBuf.Add((int)list[i].GetItemType()); } } return 2; } if (FiHoldCard3dList?.GetValue(_playerIpc) is List<InteractableCard3d> { Count: >0 } list2) { for (int j = 0; j < list2.Count; j++) { if (_holdCardsBuf.Count >= 4) { break; } InteractableCard3d val2 = list2[j]; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_Card3dUI != (Object)null && (Object)(object)val2.m_Card3dUI.m_CardUI != (Object)null) { _holdCardsBuf.Add(val2.m_Card3dUI.m_CardUI.GetCardData()); } } if (_holdCardsBuf.Count > 0) { return 3; } } object obj3 = FiViewAlbum?.GetValue(_playerIpc); bool flag = default(bool); int num; if (obj3 is bool) { flag = (bool)obj3; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return 4; } } catch { } return 0; } private bool IsAlive(FieldInfo fi) { object? obj = fi?.GetValue(_playerIpc); return (Object)((obj is Object) ? obj : null) != (Object)null; } public void StartHosting() { ErrorLine = ""; if (Role != CoopRole.None) { ErrorLine = "Already in a session."; return; } if (!InGameLevel()) { ErrorLine = "Load your shop first, then host."; return; } try { Transport transport = new Transport { KeepaliveFrame = Msg.Build(MsgType.Ping) }; transport.StartHost(CoopPlugin.Port.Value); _net = transport; Role = CoopRole.Host; StatusLine = "Hosting - waiting for a player..."; CoopPlugin.Log.LogInfo((object)$"Hosting on port {CoopPlugin.Port.Value}"); } catch (Exception ex) { ErrorLine = "Could not host: " + ex.Message; _net?.Stop(); _net = null; Role = CoopRole.None; } } public void Join(string ip) { ErrorLine = ""; if (Role != CoopRole.None) { ErrorLine = "Already in a session."; return; } if (InGameLevel()) { ErrorLine = "Join from the main menu (Title screen)."; return; } ip = (ip ?? "").Trim(); if (ip.Length == 0) { ErrorLine = "Enter the host's IP address."; return; } CoopPlugin.LastJoinIP.Value = ip; Role = CoopRole.Client; StatusLine = "Connecting to " + ip + "..."; Transport net = new Transport { KeepaliveFrame = Msg.Build(MsgType.Ping) }; _net = net; int port = CoopPlugin.Port.Value; Thread thread = new Thread((ThreadStart)delegate { try { net.StartClient(ip, port); _mainThread.Enqueue(delegate { StatusLine = "Connected - requesting world..."; SendHello(); }); } catch (Exception ex) { Exception ex2 = ex; Exception e = ex2; _mainThread.Enqueue(delegate { ErrorLine = "Could not connect: " + e.Message; Shutdown(null); }); } }); thread.IsBackground = true; thread.Name = "CoopConnect"; thread.Start(); } public void Disconnect() { Shutdown("disconnected"); } public void SendEmote() { if (_net != null && Role != CoopRole.None) { Broadcast(MsgType.Emote, delegate(BinaryWriter bw) { bw.Write((byte)1); }); } } public void ForwardContribution(byte kind, float value) { if (Role == CoopRole.Client && _net != null) { Send(1, MsgType.EconContrib, delegate(BinaryWriter bw) { bw.Write(kind); bw.Write(value); }); } } public void ForwardCardDelta(CardData card, int amount, bool isAdd) { if (Role != CoopRole.None && _net != null && card != null && amount > 0) { Broadcast(MsgType.CardDelta, delegate(BinaryWriter bw) { bw.Write(isAdd); bw.Write(amount); Msg.WriteCard(bw, card); }); } } public void ForwardOrder(int restockIndex, int count) { //IL_006b: 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) if (Role != CoopRole.Client || _net == null) { return; } RestockData rd = null; try { rd = InventoryBase.GetRestockData(restockIndex); } catch { } if (rd == null) { CoopPlugin.Log.LogWarning((object)$"order: bad restock index {restockIndex}"); return; } float lineCost = 0f; try { lineCost = CPlayerData.GetItemCost(rd.itemType) * (float)RestockManager.GetMaxItemCountInBox(rd.itemType, rd.isBigBox) * (float)count; } catch { } Send(1, MsgType.OrderRequest, delegate(BinaryWriter bw) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected I4, but got Unknown bw.Write((int)rd.itemType); bw.Write(rd.isBigBox); bw.Write(rd.name ?? ""); bw.Write(count); bw.Write(lineCost); }); } public void ForwardLicense(int restockIndex) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected I4, but got Unknown if (Role == CoopRole.None || _net == null) { return; } RestockData val = null; try { val = InventoryBase.GetRestockData(restockIndex); } catch { } if (val == null) { return; } _lastLicenseBuyTime = Time.realtimeSinceStartupAsDouble; int itemType = (int)val.itemType; bool isBig = val.isBigBox; string rdName = val.name ?? ""; if (Role == CoopRole.Host) { Broadcast(MsgType.LicenseUnlock, delegate(BinaryWriter bw) { bw.Write(itemType); bw.Write(isBig); bw.Write(rdName); }); } else { Send(1, MsgType.LicenseUnlock, delegate(BinaryWriter bw) { bw.Write(itemType); bw.Write(isBig); bw.Write(rdName); }); } } private static int ResolveRestockIndex(int itemType, bool isBig, string name, out bool sizeDiffers) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Invalid comparison between Unknown and I4 sizeDiffers = false; try { List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; for (int i = 0; i < restockDataList.Count; i++) { if (restockDataList[i] != null && (int)restockDataList[i].itemType == itemType && restockDataList[i].isBigBox == isBig) { return i; } } if (!string.IsNullOrEmpty(name)) { for (int j = 0; j < restockDataList.Count; j++) { if (restockDataList[j] != null && restockDataList[j].name == name && restockDataList[j].isBigBox == isBig) { return j; } } } sizeDiffers = true; for (int k = 0; k < restockDataList.Count; k++) { if (restockDataList[k] != null && (int)restockDataList[k].itemType == itemType) { return k; } } if (!string.IsNullOrEmpty(name)) { for (int l = 0; l < restockDataList.Count; l++) { if (restockDataList[l] != null && restockDataList[l].name == name) { return l; } } } } catch { } return -1; } private bool ApplyLicenseUnlock(int itemType, bool isBig, string name) { bool sizeDiffers; int num = ResolveRestockIndex(itemType, isBig, name, out sizeDiffers); if (num < 0) { CoopPlugin.Log.LogWarning((object)$"license unlock: no local product for type {itemType} big={isBig} '{name}'"); return false; } if (CPlayerData.GetIsItemLicenseUnlocked(num)) { return true; } GamePatches.ApplyingRemoteLicense = true; try { CPlayerData.SetUnlockItemLicense(num); try { AchievementManager.OnItemLicenseUnlocked((EItemType)itemType); } catch { } try { GameInstance.m_IsItemLicenseUnlocked = true; } catch { } try { if (itemType == 1) { TutorialManager.AddTaskValue((ETutorialTaskCondition)14, 1f); } } catch { } } finally { GamePatches.ApplyingRemoteLicense = false; } RefreshLicensePanels(); CoopPlugin.Log.LogInfo((object)$"license unlocked by partner: {(object)(EItemType)itemType} big={isBig}"); return true; } private static void RefreshLicensePanels() { try { RestockItemPanelUI[] array = Object.FindObjectsOfType<RestockItemPanelUI>(); foreach (RestockItemPanelUI obj in array) { if (FiPanelIndex?.GetValue(obj) is int num && num >= 0 && num < CPlayerData.m_IsItemLicenseUnlocked.Count && CPlayerData.GetIsItemLicenseUnlocked(num)) { object? obj2 = FiPanelLicGrp?.GetValue(obj); object? obj3 = ((obj2 is GameObject) ? obj2 : null); if (obj3 != null) { ((GameObject)obj3).SetActive(false); } object? obj4 = FiPanelUIGrp?.GetValue(obj); object? obj5 = ((obj4 is GameObject) ? obj4 : null); if (obj5 != null) { ((GameObject)obj5).SetActive(true); } } } } catch { } } private void SendCatalogDigest() { try { List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; List<RestockData> entries = new List<RestockData>(restockDataList.Count); foreach (RestockData item in restockDataList) { if (item != null) { entries.Add(item); } } Send(1, MsgType.CatalogDigest, delegate(BinaryWriter bw) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected I4, but got Unknown int num = Mathf.Min(entries.Count, 65535); bw.Write((ushort)num); for (int i = 0; i < num; i++) { bw.Write((int)entries[i].itemType); bw.Write(entries[i].isBigBox); bw.Write(Fnv(entries[i].name ?? "")); } }); } catch (Exception ex) { CoopPlugin.Log.LogWarning((object)("catalog digest: " + ex.Message)); } } private void CompareCatalogs(BinaryReader br, int connId) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected I4, but got Unknown int num = br.ReadUInt16(); HashSet<long> hashSet = new HashSet<long>(); for (int i = 0; i < num; i++) { int type = br.ReadInt32(); bool big = br.ReadBoolean(); int nameHash = br.ReadInt32(); hashSet.Add(CatalogKey(type, big, nameHash)); } List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; int num2 = 0; int num3 = 0; List<string> list = new List<string>(); foreach (RestockData item in restockDataList) { if (item == null) { continue; } if (hashSet.Contains(CatalogKey((int)item.itemType, item.isBigBox, Fnv(item.name ?? "")))) { num3++; continue; } num2++; if (list.Count < 6) { list.Add(item.name); } } int num4 = hashSet.Count - num3; if (num2 == 0 && num4 == 0) { CoopPlugin.Log.LogInfo((object)$"catalog check: identical ({num3} products)"); return; } string value; string arg = (PeerNames.TryGetValue(connId, out value) ? value : "joiner"); string summary = $"heads-up: product catalogs differ ({num2} only on host, {num4} only on {arg}) - mismatched items can't be ordered; match your content packs"; CoopPlugin.Log.LogWarning((object)("catalog check: " + summary + ((list.Count > 0) ? (" | host-only e.g.: " + string.Join(" / ", list.ToArray())) : ""))); RegisterLine = summary; RegisterLineTimer = 10f; Send(connId, MsgType.Toast, delegate(BinaryWriter bw) { bw.Write(summary); }); } private void LogCatalogCandidates(string name) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected I4, but got Unknown try { if (string.IsNullOrEmpty(name)) { return; } string text = name.Split(new char[1] { ' ' })[0]; List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; List<string> list = new List<string>(); foreach (RestockData item in restockDataList) { if (list.Count < 8) { if (item != null && item.name != null && item.name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { list.Add($"{item.name} (type {(int)item.itemType}, big={item.isBigBox})"); } continue; } break; } CoopPlugin.Log.LogInfo((object)((list.Count > 0) ? ("similar host entries: " + string.Join(" | ", list.ToArray())) : ("no host entries resembling '" + text + "'"))); } catch { } } private static long CatalogKey(int type, bool big, int nameHash) { return (long)((ulong)((long)type << 33) ^ ((ulong)(uint)nameHash << 1)) ^ (long)(big ? 1 : 0); } private static int Fnv(string s) { uint num = 2166136261u; for (int i = 0; i < s.Length; i++) { num ^= s[i]; num *= 16777619; } return (int)num; } public void ForwardFurniture(int objType, Vector3 pos, Quaternion rot) { //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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (Role == CoopRole.Client && _net != null) { Send(1, MsgType.FurnitureOrder, delegate(BinaryWriter bw) { bw.Write(objType); bw.Write(pos.x); bw.Write(pos.y); bw.Write(pos.z); bw.Write(rot.x); bw.Write(rot.y); bw.Write(rot.z); bw.Write(rot.w); }); } } public void ForwardItemPrice(EItemType itemType, float price) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (Role == CoopRole.Client && _net != null) { Send(1, MsgType.ItemPriceContrib, delegate(BinaryWriter bw) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected I4, but got Unknown bw.Write((int)itemType); bw.Write(price); }); } } public void ForwardCardPrice(CardData card, float price) { if (Role != CoopRole.None && _net != null && card != null) { Broadcast(MsgType.CardPriceSet, delegate(BinaryWriter bw) { Msg.WriteCard(bw, card); bw.Write(price); }); } } private void Shutdown(string reason) { if (_net != null) { try { Broadcast(MsgType.Bye, null); } catch { } _net.Stop(); _net = null; } _avatars.Clear(); PeerNames.Clear(); _saveBuf = null; _saveExpected = -1; _pendingSave = null; _bundleBuf = null; _bundleExpected = -1; _worldRequested = false; _hasLastPos = false; _lastCoinSent = double.MinValue; _lastPriceHash = 0; _lastProgressSent = long.MinValue; _world.Reset(); _npcs.Reset(); _cardShelves.Reset(); _objMoves.Reset(); _boxes.Reset(); _population.Reset(); _registerMirror.Reset(); ModulesReset(); PromptLine = ""; _lastShopNameSent = null; _steamLobby.Leave(); IsSteamSession = false; HostPassword = ""; _joinPassword = ""; _selfId = -1; _relayIds.Clear(); _pendingKicks.Clear(); Application.runInBackground = false; Role = CoopRole.None; if (reason != null) { StatusLine = "Not connected (" + reason + ")"; CoopPlugin.Log.LogInfo((object)("Session ended: " + reason)); } } private void Send(int connId, MsgType type, Action<BinaryWriter> write) { _net?.Send(connId, Msg.Build(type, write)); } private void Broadcast(MsgType type, Action<BinaryWriter> write) { _net?.Broadcast(Msg.Build(type, write)); } private void BroadcastTransient(MsgType type, Action<BinaryWriter> write) { _net?.BroadcastTransient(Msg.Build(type, write)); } private void Update() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_0611: Unknown result type (might be due to invalid IL or missing references) //IL_0622: Unknown result type (might be due to invalid IL or missing references) Action result; while (_mainThread.TryDequeue(out result)) { try { result(); } catch (Exception ex) { CoopPlugin.Log.LogError((object)ex); } } AutoTick(Time.deltaTime); if (Input.GetKeyDown(CoopPlugin.UiToggleKey.Value)) { _ui.Visible = !_ui.Visible; } if (Role != CoopRole.None && Input.GetKeyDown(CoopPlugin.EmoteKey.Value) && !CoopUI.TextFieldFocused) { SendEmote(); } if (_serveThrottle > 0f) { _serveThrottle -= Time.deltaTime; } if (RegisterLineTimer > 0f) { RegisterLineTimer -= Time.deltaTime; if (RegisterLineTimer <= 0f) { RegisterLine = ""; } } bool serveTap = Input.GetKeyDown(CoopPlugin.ServeKey.Value); if (Role == CoopRole.Client && _serveThrottle <= 0f && InGameLevel() && (serveTap || Input.GetKey(CoopPlugin.ServeKey.Value)) && !CoopUI.TextFieldFocused) { _serveThrottle = 0.25f; Guarded("serve", delegate { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Transform val2 = ResolvePlayer(); int idx = (((Object)(object)val2 != (Object)null) ? RegisterServe.FindNearestCounter(val2.position, CoopPlugin.ServeReach.Value, !serveTap) : (-1)); if (idx < 0 || !_trades.HasOffer(idx)) { if (idx < 0) { if (serveTap) { RegisterLine = "walk up to the register first"; RegisterLineTimer = 2f; } } else { Send(1, MsgType.ServeRequest, delegate(BinaryWriter bw) { bw.Write(idx); }); } } }); } if (Role == CoopRole.Client && _serveThrottle <= 0f && InGameLevel() && Input.GetMouseButtonDown(0) && !CoopUI.TextFieldFocused) { Guarded("serve-click", delegate { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(main.ScreenPointToRay(Input.mousePosition), ref val2, 6f) && _registerMirror.TryGetPropCounter(((RaycastHit)(ref val2)).collider, out var propIdx)) { _serveThrottle = 0.25f; Send(1, MsgType.ServeRequest, delegate(BinaryWriter bw) { bw.Write(propIdx); }); } else { Transform val3 = ResolvePlayer(); int near = (((Object)(object)val3 != (Object)null) ? RegisterServe.FindNearestCounter(val3.position, CoopPlugin.ServeReach.Value, quiet: true) : (-1)); if (near >= 0 && _registerMirror.IsPaymentPhase(near)) { _serveThrottle = 0.3f; Send(1, MsgType.ServeRequest, delegate(BinaryWriter bw) { bw.Write(near); }); } } } }); } if (_net == null) { return; } Guarded("net-pump", _actNetPump); if (!Application.runInBackground) { Application.runInBackground = true; CoopPlugin.Log.LogInfo((object)"Forced runInBackground=true for the co-op session"); } int result2; while (_net.Connects.TryDequeue(out result2)) { CoopPlugin.Log.LogInfo((object)("Connection " + result2 + " opened")); if (Role == CoopRole.Host) { ModulesForceResend(); } } int result3; while (_net.Disconnects.TryDequeue(out result3)) { string value; string text = (PeerNames.TryGetValue(result3, out value) ? value : ("player " + result3)); PeerNames.Remove(result3); _avatars.Remove(result3); if (Role == CoopRole.Host) { BroadcastRoster(); StatusLine = ((_net.ConnectionCount == 0) ? "Hosting - waiting for a player..." : $"Hosting - {_net.ConnectionCount} player(s)"); CoopPlugin.Log.LogInfo((object)(text + " left")); } else if (Role == CoopRole.Client) { ErrorLine = "Lost connection to the host. You can keep walking around; nothing here touches your own saves."; Shutdown("host connection lost"); return; } } _dispatchBuf.Clear(); InMsg result4; while (_net != null && _net.Incoming.TryDequeue(out result4)) { _dispatchBuf.Add(result4); } if (_dispatchBuf.Count > 8) { _dispatchSeen.Clear(); for (int num = _dispatchBuf.Count - 1; num >= 0; num--) { MsgType type = _dispatchBuf[num].Type; if (type == MsgType.PlayerState || type == MsgType.RegisterState || type == MsgType.BoxState || type == MsgType.PopState) { long item = (long)(((ulong)type << 32) | (uint)_dispatchBuf[num].ConnId); if (!_dispatchSeen.Add(item)) { _dispatchBuf[num] = default(InMsg); } } } } for (int num2 = 0; num2 < _dispatchBuf.Count; num2++) { if (_dispatchBuf[num2].Type != 0) { try { Dispatch(_dispatchBuf[num2]); } catch (Exception arg) { CoopPlugin.Log.LogError((object)$"Dispatch {_dispatchBuf[num2].Type}: {arg}"); } if (_net == null) { break; } } } if (_net == null) { return; } float deltaTime = Time.deltaTime; if (_errLogCooldown > 0f) { _errLogCooldown -= deltaTime; } FlushPendingCardWork(); _dt = deltaTime; Guarded("avatars", _actAvatars); _syncActive = Role != CoopRole.None && _net.ConnectionCount > 0 && InGameLevel(); Guarded("world", _actWorld); Guarded("cardshelves", _actCardShelves); Guarded("objmoves", _actObjMoves); Guarded("boxes", _actBoxes); Guarded("population", _actPopulation); Guarded("modules", _actModules); if (Role == CoopRole.Client) { Guarded("npc-puppets", _actNpcPuppets); Guarded("register-mirror", _actRegisterMirror); _npcSweepTimer += deltaTime; if (_npcSweepTimer >= 2f && InGameLevel()) { _npcSweepTimer -= 2f; Guarded("npc-sweep", _actNpcSweep); } } _stateTimer += deltaTime; Guarded("state-send", _actStateSend); _diagTimer += deltaTime; if (_diagTimer >= 15f) { _diagTimer -= 15f; Transform val = (InGameLevel() ? ResolvePlayer() : null); string text2 = (((Object)(object)val != (Object)null) ? $"({val.position.x:F1},{val.position.y:F1},{val.position.z:F1})" : "n/a"); string text3 = ""; if (InGameLevel()) { try { int num3 = NpcSync.CountLocalActiveNpcs(); text3 = ((Role == CoopRole.Client) ? $" puppets={_npcs.PuppetCount} localNpcs={num3}(should be 0)" : $" liveNpcs={num3}"); } catch { } } CoopPlugin.Log.LogInfo((object)$"diag: role={Role} conns={_net.ConnectionCount} sentStates={_diagSent} recvStates={_diagRecvStates} inGame={InGameLevel()} pos={text2}{text3}"); } for (int num4 = _pendingKicks.Count - 1; num4 >= 0; num4--) { float num5 = _pendingKicks[num4].Value - deltaTime; if (num5 <= 0f) { int key = _pendingKicks[num4].Key; _pendingKicks.RemoveAt(num4); _net.Kick(key); } else { _pendingKicks[num4] = new KeyValuePair<int, float>(_pendingKicks[num4].Key, num5); } } _pingTimer += deltaTime; if (_pingTimer >= 2f) { _pingTimer = 0f; Broadcast(MsgType.Ping, null); foreach (int item2 in _net.ConnIds()) { if (_net.SecondsSinceLastRecv(item2) > _net.TimeoutSeconds) { CoopPlugin.Log.LogWarning((object)("Connection " + item2 + " timed out")); _net.Kick(item2); } } } if (Role == CoopRole.Host) { HostTick(deltaTime); } } private void AutoTick(float dt) { //IL_01cd: Unknown result type (might be due to invalid IL or missing references) if ((_autoHostSlot < 0 && _autoJoinIp == null) || _autoPhase >= 99) { return; } _autoTimer += dt; if (_autoHostSlot >= 0) { if (_autoPhase == 0 && _autoTimer > 6f && !InGameLevel() && (Object)(object)CSingleton<CGameManager>.Instance != (Object)null) { CoopPlugin.Log.LogInfo((object)$"AUTO: loading slot {_autoHostSlot}..."); SaveTransfer.ForceLoadSlot(_autoHostSlot); _autoPhase = 1; _autoTimer = 0f; } else if (_autoPhase == 1 && InGameLevel() && GameInstance.m_FinishedSavefileLoading) { _autoPhase = 2; _autoTimer = 0f; } else if (_autoPhase == 2 && _autoTimer > 3f) { CoopPlugin.Log.LogInfo((object)"AUTO: hosting now"); StartHosting(); _autoPhase = 99; } } else if (_autoJoinIp != null) { if (_autoPhase == 0 && _autoTimer > 10f && !InGameLevel() && (Object)(object)CSingleton<CGameManager>.Instance != (Object)null) { CoopPlugin.Log.LogInfo((object)("AUTO: joining " + _autoJoinIp + "...")); Join(_autoJoinIp); _autoPhase = 99; } } else if (_autoJoinSteamLobby != 0L && _autoPhase == 0 && _autoTimer > 10f && !InGameLevel() && (Object)(object)CSingleton<CGameManager>.Instance != (Object)null) { CoopPlugin.Log.LogInfo((object)$"AUTO: joining Steam lobby {_autoJoinSteamLobby}..."); JoinSteam(new CSteamID(_autoJoinSteamLobby)); _autoPhase = 99; } } private void OnLocalWorldChanges(List<WorldSync.Entry> changes) { if (Role == CoopRole.Host) { Broadcast(MsgType.ShelfDelta, delegate(BinaryWriter bw) { WorldSync.WriteEntries(bw, changes); }); } else if (Role == CoopRole.Client) { Send(1, MsgType.ShelfRequest, delegate(BinaryWriter bw) { WorldSync.WriteEntries(bw, changes); }); } } private void HostTick(float dt) { //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Expected I4, but got Unknown if (_net.ConnectionCount == 0) { return; } if (InGameLevel()) { Guarded("npc-collect", _actNpcCollect); Guarded("register-collect", _actRegisterCollect); } _priceTimer += dt; if (_priceTimer >= 3f) { _priceTimer -= 3f; try { List<float> prices = CPlayerData.m_SetItemPriceList; int num = 17; for (int i = 0; i < prices.Count; i++) { if (prices[i] != 0f) { num = num * 31 + i; num = num * 31 + prices[i].GetHashCode(); } } if (num != _lastPriceHash) { _lastPriceHash = num; Broadcast(MsgType.PriceList, delegate(BinaryWriter bw) { int num5 = 0; for (int j = 0; j < prices.Count; j++) { if (prices[j] != 0f) { num5++; } } bw.Write(num5); for (int k = 0; k < prices.Count; k++) { if (prices[k] != 0f) { bw.Write(k); bw.Write(prices[k]); } } }); } } catch (Exception ex) { CoopPlugin.Log.LogWarning((object)("price sync: " + ex.Message)); } } _shopNameTimer += dt; if (_shopNameTimer >= 3f) { _shopNameTimer -= 3f; string name = CPlayerData.GetPlayerName(); if (name != _lastShopNameSent) { _lastShopNameSent = name; Broadcast(MsgType.ShopName, delegate(BinaryWriter bw) { bw.Write(name); }); } } _econTimer += dt; if (_econTimer >= 0.5f) { _econTimer -= 0.5f; double coin = CPlayerData.m_CoinAmountDouble; if (Math.Abs(coin - _lastCoinSent) > 0.0001) { _lastCoinSent = coin; float coinF = CPlayerData.m_CoinAmount; Broadcast(MsgType.CoinSet, delegate(BinaryWriter bw) { bw.Write(coin); bw.Write(coinF); }); } int exp = CPlayerData.m_ShopExpPoint; int level = CPlayerData.m_ShopLevel; int fame = CPlayerData.m_FamePoint; long num2 = ((long)level << 40) ^ ((long)fame << 20) ^ (uint)exp; if (num2 != _lastProgressSent) { _lastProgressSent = num2; Broadcast(MsgType.ProgressSet, delegate(BinaryWriter bw) { bw.Write(exp); bw.Write(level); bw.Write(fame); }); } } _lightSyncTimer += dt; if (_lightSyncTimer >= 5f) { _lightSyncTimer -= 5f; try { if ((Object)(object)_lightManager == (Object)null) { _lightManager = Object.FindObjectOfType<LightManager>(); } if ((Object)(object)_lightManager != (Object)null && MiUpdateLightData != null && CPlayerData.m_LightTimeData != null) { MiUpdateLightData.Invoke(_lightManager, null); string lightJson = JsonUtility.ToJson((object)CPlayerData.m_LightTimeData); _lightHeal += 5f; if (lightJson != _lastLightJson || _lightHeal >= 15f) { _lastLightJson = lightJson; _lightHeal = 0f; Broadcast(MsgType.LightState, delegate(BinaryWriter bw) { bw.Write(lightJson); }); } } } catch (Exception ex2) { CoopPlugin.Log.LogWarning((object)("light sync: " + ex2.Message)); } } _cardResyncTimer += dt; if (_cardResyncTimer >= 12f && InGameLevel()) { _cardResyncTimer -= 12f; try { List<CardShelfSync.Entry> full = _cardShelves.BuildFullState(); if (full.Count > 0) { Broadcast(MsgType.CardShelfDelta, delegate(BinaryWriter bw) { CardShelfSync.WriteEntries(bw, full); }); } } catch (Exception ex3) { CoopPlugin.Log.LogWarning((object)("card resync: " + ex3.Message)); } } _licenseSyncTimer += dt; if (_licenseSyncTimer >= 10f && InGameLevel()) { _licenseSyncTimer -= 10f; try { List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; List<bool> isItemLicenseUnlocked = CPlayerData.m_IsItemLicenseUnlocked; List<RestockData> unlocked = new List<RestockData>(); for (int num3 = 0; num3 < restockDataList.Count && num3 < isItemLicenseUnlocked.Count; num3++) { if (isItemLicenseUnlocked[num3] && restockDataList[num3] != null) { unlocked.Add(restockDataList[num3]); } } bool scanner = CPlayerData.m_IsScannerRestockUnlocked; int num4 = 17; foreach (RestockData item in unlocked) { num4 = num4 * 31 + ((item.itemType << 1) | item.isBigBox); } num4 = num4 * 31 + (scanner ? 1 : 0); _licenseHeal += 10f; if (num4 != _lastLicenseHash || _licenseHeal >= 60f) { _lastLicenseHash = num4; _licenseHeal = 0f; Broadcast(MsgType.LicenseState, delegate(BinaryWriter bw) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected I4, but got Unknown bw.Write(scanner); bw.Write((ushort)unlocked.Count); foreach (RestockData item2 in unlocked) { bw.Write((int)item2.itemType); bw.Write(item2.isBigBox); } }); } } catch (Exception ex4) { CoopPlugin.Log.LogWarning((object)("license sync: " + ex4.Message)); } } _dayTimer += dt; if (!(_dayTimer >= 2f)) { return; } _dayTimer -= 2f; int hour = 8; int min = 0; try { if ((Object)(object)_lightManager == (Object)null) { _lightManager = Object.FindObjectOfType<LightManager>(); } if ((Object)(object)_lightManager != (Object)null) { if (FiTimeHour != null) { hour = (int)FiTimeHour.GetValue(_lightManager); } if (FiTimeMin != null) { min = (int)FiTimeMin.GetValue(_lightManager); } } } catch { } int day = CPlayerData.m_CurrentDay; Broadcast(MsgType.DayTime, delegate(BinaryWriter bw) { bw.Write(day); bw.Write(hour); bw.Write(min); }); } private void Dispatch(InMsg msg) { //IL_09c1: Unknown result type (might be due to invalid IL or missing references) //IL_09c6: Unknown result type (might be due to invalid IL or missing references) //IL_0a39: Unknown result type (might be due to invalid IL or missing references) //IL_11d6: Unknown result type (might be due to invalid IL or missing references) //IL_11db: Unknown result type (might be due to invalid IL or missing references) //IL_11e3: Unknown result type (might be due to invalid IL or missing references) //IL_11e8: Unknown result type (might be due to invalid IL or missing references) //IL_11f0: Unknown result type (might be due to invalid IL or missing references) //IL_11f5: Unknown result type (might be due to invalid IL or missing references) //IL_11fd: Unknown result type (might be due to invalid IL or missing references) //IL_1202: Unknown result type (might be due to invalid IL or missing references) //IL_120f: Unknown result type (might be due to invalid IL or missing references) //IL_121c: Unknown result type (might be due to invalid IL or missing references) //IL_1229: Unknown result type (might be due to invalid IL or missing references) //IL_1236: Unknown result type (might be due to invalid IL or missing references) //IL_1243: Unknown result type (might be due to invalid IL or missing references) //IL_1252: Expected O, but got Unknown //IL_0e63: Unknown result type (might be due to invalid IL or missing references) //IL_0e6d: Expected O, but got Unknown //IL_0e6d: Unknown result type (might be due to invalid IL or missing references) //IL_0e77: Expected O, but got Unknown //IL_1768: Unknown result type (might be due to invalid IL or missing references) //IL_1772: Expected O, but got Unknown //IL_0e7f: Unknown result type (might be due to invalid IL or missing references) //IL_0e89: Expected O, but got Unknown //IL_26e4: Unknown result type (might be due to invalid IL or missing references) //IL_26ee: Expected O, but got Unknown //IL_26f6: Unknown result type (might be due to invalid IL or missing references) //IL_2700: Expected O, but got Unknown //IL_2709: Unknown result type (might be due to invalid IL or missing references) //IL_2713: Expected O, but got Unknown //IL_271c: Unknown result type (might be due to invalid IL or missing references) //IL_2726: Expected O, but got Unknown //IL_10bc: Unknown result type (might be due to invalid IL or missing references) //IL_0c3d: Unknown result type (might be due to invalid IL or missing references) //IL_0c47: Expected O, but got Unknown //IL_1504: Unknown result type (might be due to invalid IL or missing references) //IL_1506: Unknown result type (might be due to invalid IL or missing references) //IL_22d5: Unknown result type (might be due to invalid IL or missing references) //IL_22df: Expected O, but got Unknown //IL_089d: Unknown result type (might be due to invalid IL or missing references) //IL_08a7: Expected O, but got Unknown //IL_266c: Unknown result type (might be due to invalid IL or missing references) //IL_2674: Unknown result type (might be due to invalid IL or missing references) //IL_0932: Unknown result type (might be due to invalid IL or missing references) //IL_093c: Expected O, but got Unknown switch (msg.Type) { case MsgType.Hello: { if (Role != CoopRole.Host) { break; } using BinaryReader binaryReader26 = Msg.Reader(msg.Payload); string text7 = binaryReader26.ReadString(); string text8 = binaryReader26.ReadString(); string text9 = binaryReader26.ReadString(); string text10 = binaryReader26.ReadString(); string text11 = binaryReader26.ReadString(); if (text7 != "1.0.6") { RejectConn(msg.ConnId, "version mismatch - host runs CardShopCoop 1.0.6, you have " + text7); break; } if (HostPassword.Length > 0 && text9 != HostPassword) { RejectConn(msg.ConnId, "wrong password"); break; } if (text10 != ModParity.PluginHash()) { RejectConn(msg.ConnId, "your mod set differs from the host's - both players need identical mods (same versions)"); break; } string text12 = ModParity.EnumHash(); if (text11 != "none" && text12 != "none" && text11 != text12) { try { byte[] data = File.ReadAllBytes(ModParity.EnumFilePath()); byte[] gz = Msg.Gzip(data); Send(msg.ConnId, MsgType.EnumSync, delegate(BinaryWriter bw) { bw.Write(gz.Length); bw.Write(gz); }); } catch (Exception ex3) { CoopPlugin.Log.LogWarning((object)("enum sync send: " + ex3.Message)); } RejectConn(msg.ConnId, "your custom-card database differed - it has been synced from the host; RESTART your game, then join again"); } else { PeerNames[msg.ConnId] = text8; _avatars.SetName(msg.ConnId, text8); StatusLine = "Hosting - " + text8 + " joined!"; CoopPlugin.Log.LogInfo((object)(text8 + " joined, sending world...")); SendWorldTo(msg.ConnId); BroadcastRoster(); } break; } case MsgType.Welcome: if (Role == CoopRole.Client) { using (BinaryReader binaryReader3 = Msg.Reader(msg.Payload)) { binaryReader3.ReadString(); string text3 = binaryReader3.ReadString(); _saveExpected = binaryReader3.ReadInt32(); _hostSlot = binaryReader3.ReadInt32(); _bundleExpected = binaryReader3.ReadInt32(); _selfId = binaryReader3.ReadByte(); PeerNames[msg.ConnId] = text3; _avatars.SetName(msg.ConnId, text3); _saveBuf = new MemoryStream((_saveExpected > 0) ? _saveExpected : 1024); _bundleBuf = new MemoryStream((_bundleExpected > 0) ? _bundleExpected : 16); StatusLine = $"Downloading {text3}'s shop ({(_saveExpected + _bundleExpected) / 1024} KB)..."; break; } } break; case MsgType.SaveChunk: { if (Role != CoopRole.Client || _saveBuf == null) { break; } using BinaryReader binaryReader14 = Msg.Reader(msg.Payload); binaryReader14.ReadInt32(); int count2 = binaryReader14.ReadInt32(); byte[] array2 = binaryReader14.ReadBytes(count2); _saveBuf.Write(array2, 0, array2.Length); if (_saveExpected > 0) { StatusLine = $"downloading shop... {Math.Min(100L, _saveBuf.Length * 100 / _saveExpected)}%"; } break; } case MsgType.SaveDone: { if (Role != CoopRole.Client || _saveBuf == null || _worldRequested) { break; } byte[] array3 = _saveBuf.ToArray(); _saveBuf = null; if (_saveExpected >= 0 && array3.Length != _saveExpected) { ErrorLine = $"World download looked corrupted ({array3.Length}/{_saveExpected} bytes) - try again."; Shutdown("bad download"); break; } try { array3 = Msg.Gunzip(array3); } catch { ErrorLine = "World download could not be unpacked - try again."; Shutdown("bad download"); break; } if (array3.Length < 1024 || array3[0] != 123) { ErrorLine = "World download looked corrupted - try again."; Shutdown("bad download"); } else { _pendingSave = array3; StatusLine = "shop received - downloading mod data..."; } break; } case MsgType.BundleChunk: { if (Role != CoopRole.Client || _bundleBuf == null) { break; } using BinaryReader binaryReader7 = Msg.Reader(msg.Payload); binaryReader7.ReadInt32(); int count = binaryReader7.ReadInt32(); byte[] array = binaryReader7.ReadBytes(count); _bundleBuf.Write(array, 0, array.Length); if (_bundleExpected > 0) { StatusLine = $"downloading mod data... {Math.Min(100L, _bundleBuf.Length * 100 / _bundleExpected)}%"; } break; } case MsgType.BundleDone: { if (Role != CoopRole.Client || _worldRequested || _pendingSave == null) { break; } byte[] array4 = ((_bundleBuf != null) ? _bundleBuf.ToArray() : new byte[0]); _bundleBuf = null; _worldRequested = true; StatusLine = "World received - loading..."; try { if (array4.Length != 0) { array4 = Msg.Gunzip(array4); } SidecarTransfer.ApplyBundle(array4, _hostSlot, SaveTransfer.CoopSlot); } catch (Exception ex2) { CoopPlugin.Log.LogWarning((object)("Sidecar apply failed (continuing): " + ex2.Message)); } SaveTransfer.ApplyAndLoad(_pendingSave); _pendingSave = null; break; } case MsgType.ShelfDelta: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br6 = Msg.Reader(msg.Payload)) { _world.ApplyRemote(WorldSync.ReadEntries(br6)); break; } } break; case MsgType.ShelfRequest: { if (Role != CoopRole.Host || !InGameLevel()) { break; } using BinaryReader br29 = Msg.Reader(msg.Payload); List<WorldSync.Entry> entries3 = WorldSync.ReadEntries(br29); _world.ApplyRemote(entries3); if (_net.ConnectionCount > 1) { Broadcast(MsgType.ShelfDelta, delegate(BinaryWriter bw) { WorldSync.WriteEntries(bw, entries3); }); } break; } case MsgType.PriceList: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader22 = Msg.Reader(msg.Payload); int num33 = binaryReader22.ReadInt32(); List<float> setItemPriceList2 = CPlayerData.m_SetItemPriceList; GamePatches.ApplyingRemotePrice = true; try { _incomingPriced.Clear(); int num34 = 0; for (int num35 = 0; num35 < num33; num35++) { int num36 = binaryReader22.ReadInt32(); float num37 = binaryReader22.ReadSingle(); _incomingPriced.Add(num36); if (num36 >= 0 && num36 <= 500000) { while (setItemPriceList2.Count <= num36) { setItemPriceList2.Add(0f); num34++; } if (Math.Abs(setItemPriceList2[num36] - num37) > 0.0001f) { setItemPriceList2[num36] = num37; CEventManager.QueueEvent((CEvent)new CEventPlayer_ItemPriceChanged((EItemType)num36, num37)); } } } if (num34 > 0) { CoopPlugin.Log.LogInfo((object)$"price apply: grew the price table by {num34} entries for modded items"); } foreach (int item in _clientPriced) { if (!_incomingPriced.Contains(item) && item >= 0 && item < setItemPriceList2.Count && setItemPriceList2[item] != 0f) { setItemPriceList2[item] = 0f; CEventManager.QueueEvent((CEvent)new CEventPlayer_ItemPriceChanged((EItemType)item, 0f)); } } HashSet<int> clientPriced = _clientPriced; _clientPriced = _incomingPriced; _incomingPriced = clientPriced; break; } finally { GamePatches.ApplyingRemotePrice = false; } } case MsgType.PlayerState: { using BinaryReader binaryReader21 = Msg.Reader(msg.Payload); Vector3 pos = new Vector3(binaryReader21.ReadSingle(), binaryReader21.ReadSingle(), binaryReader21.ReadSingle()); float yaw = binaryReader21.ReadSingle(); float speed = binaryReader21.ReadSingle(); byte hold = binaryReader21.ReadByte(); ReadHoldPayload(binaryReader21, hold, out var holdTypes, out var holdCards); _diagRecvStates++; _avatars.UpdateState(msg.ConnId, pos, yaw, speed, hold, holdTypes, holdCards); if (PeerNames.TryGetValue(msg.ConnId, out var value4)) { _avatars.SetName(msg.ConnId, value4); } if (Role == CoopRole.Host && _net.ConnectionCount > 1) { byte[] frame = Msg.Build(MsgType.RelayState, delegate(BinaryWriter bw) { bw.Write((byte)msg.ConnId); bw.Write(pos.x); bw.Write(pos.y); bw.Write(pos.z); bw.Write(yaw); bw.Write(speed); bw.Write(hold); WriteHoldPayload(bw, hold, holdTypes, holdCards); }); foreach (int item2 in _net.ConnIds()) { if (item2 != msg.ConnId) { _net.SendTransient(item2, frame); } } } if (_gotStateFrom.Add(msg.ConnId)) { string value5; string text6 = (PeerNames.TryGetValue(msg.ConnId, out value5) ? value5 : ("player " + msg.ConnId)); CoopPlugin.Log.LogInfo((object)("Position link active with " + text6)); if (Role == CoopRole.Host) { StatusLine = "Hosting - " + text6 + " is in your shop!"; } } break; } case MsgType.CoinSet: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader19 = Msg.Reader(msg.Payload); double num28 = binaryReader19.ReadDouble(); float num29 = binaryReader19.ReadSingle(); if (!_loggedEconLink) { _loggedEconLink = true; CoopPlugin.Log.LogInfo((object)"Economy link active (host wallet mirrored)"); } if (Math.Abs(CPlayerData.m_CoinAmountDouble - num28) > 0.0001) { CEventManager.QueueEvent((CEvent)new CEventPlayer_SetCoin(num29, num28)); } break; } case MsgType.DayTime: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader17 = Msg.Reader(msg.Payload); int num18 = binaryReader17.ReadInt32(); int num19 = binaryReader17.ReadInt32(); int num20 = binaryReader17.ReadInt32(); if (!_loggedTimeLink) { _loggedTimeLink = true; CoopPlugin.Log.LogInfo((object)$"Time link active (Day {num18} {num19:00}:{num20:00})"); } HostTimeLine = $"Day {num18 + 1} {num19:00}:{num20:00}"; bool flag3 = num18 != CPlayerData.m_CurrentDay; CPlayerData.m_CurrentDay = num18; CPlayerData.m_IsShopOnceOpen = true; try { if ((Object)(object)_lightManager == (Object)null) { _lightManager = Object.FindObjectOfType<LightManager>(); } if ((Object)(object)_lightManager != (Object)null) { if (flag3 && InGameLevel() && MiDayReset != null) { GamePatches.AllowNextDayStarted = true; ((MonoBehaviour)_lightManager).StartCoroutine((IEnumerator)MiDayReset.Invoke(_lightManager, null)); CoopPlugin.Log.LogInfo((object)$"Mirroring host day change -> Day {num18}"); } else { FiTimeHour?.SetValue(_lightManager, num19); FiTimeMin?.SetValue(_lightManager, num20); FiTimeMinFloat?.SetValue(_lightManager, (float)num20); FiHasDayEnded?.SetValue(_lightManager, false); } } break; } catch { break; } } case MsgType.ProgressSet: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader13 = Msg.Reader(msg.Payload); int num13 = binaryReader13.ReadInt32(); int num14 = binaryReader13.ReadInt32(); int num15 = binaryReader13.ReadInt32(); int shopLevel = CPlayerData.m_ShopLevel; CPlayerData.m_ShopLevel = num14; CEventManager.QueueEvent((CEvent)new CEventPlayer_SetShopExp(num13)); CEventManager.QueueEvent((CEvent)new CEventPlayer_SetFame(num15)); if (num14 > shopLevel) { CEventManager.QueueEvent((CEvent)new CEventPlayer_ShopLeveledUp(num14)); } break; } case MsgType.Emote: _avatars.ShowEmote(msg.ConnId); RelayTagToOthers(msg.ConnId, 0); break; case MsgType.Activity: { int num10 = -1; try { using BinaryReader binaryReader9 = Msg.Reader(msg.Payload); binaryReader9.ReadByte(); num10 = binaryReader9.ReadInt32(); } catch { } _avatars.ShowTag(msg.ConnId, "opening a pack!", 3f); _avatars.ShowPackOpen(msg.ConnId, num10); RelayTagToOthers(msg.ConnId, 1, num10); break; } case MsgType.Roster: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader4 = Msg.Reader(msg.Payload); int num5 = binaryReader4.ReadByte(); HashSet<int> seen = new HashSet<int>(); for (int num6 = 0; num6 < num5; num6++) { int num7 = binaryReader4.ReadByte(); string text4 = binaryReader4.ReadString(); if (num7 != _selfId) { seen.Add(num7); _rosterNames[num7] = text4; if (_relayIds.Add(num7)) { CoopPlugin.Log.LogInfo((object)("peer in shop: " + text4)); } _avatars.SetName(1000 + num7, text4); } } _relayIds.RemoveWhere(delegate(int id) { if (seen.Contains(id)) { return false; } _avatars.Remove(1000 + id); return true; }); break; } case MsgType.RelayState: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader30 = Msg.Reader(msg.Payload); int num41 = binaryReader30.ReadByte(); Vector3 pos2 = default(Vector3); ((Vector3)(ref pos2))..ctor(binaryReader30.ReadSingle(), binaryReader30.ReadSingle(), binaryReader30.ReadSingle()); float yaw2 = binaryReader30.ReadSingle(); float speed2 = binaryReader30.ReadSingle(); byte b3 = binaryReader30.ReadByte(); ReadHoldPayload(binaryReader30, b3, out var types, out var cards); if (num41 != _selfId) { _avatars.UpdateState(1000 + num41, pos2, yaw2, speed2, b3, types, cards); if (_rosterNames.TryGetValue(num41, out var value7)) { _avatars.SetName(1000 + num41, value7); } } break; } case MsgType.RelayTag: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader28 = Msg.Reader(msg.Payload); int num40 = binaryReader28.ReadByte(); byte b2 = binaryReader28.ReadByte(); int packIndex = -1; try { packIndex = binaryReader28.ReadInt32(); } catch { } if (num40 != _selfId) { if (b2 == 0) { _avatars.ShowEmote(1000 + num40); break; } _avatars.ShowTag(1000 + num40, "opening a pack!", 3f); _avatars.ShowPackOpen(1000 + num40, packIndex); } break; } case MsgType.CardDelta: { using BinaryReader binaryReader27 = Msg.Reader(msg.Payload); bool isAdd = binaryReader27.ReadBoolean(); int amount = binaryReader27.ReadInt32(); CardData card2 = new CardData { expansionType = (ECardExpansionType)binaryReader27.ReadInt32(), monsterType = (EMonsterType)binaryReader27.ReadInt32(), borderType = (ECardBorderType)binaryReader27.ReadInt32(), isFoil = binaryReader27.ReadBoolean(), isDestiny = binaryReader27.ReadBoolean(), isChampionCard = binaryReader27.ReadBoolean(), isNew = binaryReader27.ReadBoolean(), cardGrade = binaryReader27.ReadInt32(), gradedCardIndex = binaryReader27.ReadInt32() }; if (!InGameLevel()) { _pendingCardDeltas.Add(new PendingCard { IsAdd = isAdd, Amount = amount, Card = card2 }); } else { ApplyCardDelta(isAdd, amount, card2); } break; } case MsgType.NpcState: if (Role == CoopRole.Client) { using (BinaryReader br24 = Msg.Reader(msg.Payload)) { _npcs.ApplyBatch(br24, InGameLevel()); break; } } break; case MsgType.CardShelfDelta: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br21 = Msg.Reader(msg.Payload)) { _cardShelves.ApplyRemote(CardShelfSync.ReadEntries(br21)); break; } } break; case MsgType.CardShelfRequest: { if (Role != CoopRole.Host || !InGameLevel()) { break; } using BinaryReader br17 = Msg.Reader(msg.Payload); List<CardShelfSync.Entry> entries2 = CardShelfSync.ReadEntries(br17); _cardShelves.ApplyRemote(entries2); if (_net.ConnectionCount > 1) { Broadcast(MsgType.CardShelfDelta, delegate(BinaryWriter bw) { CardShelfSync.WriteEntries(bw, entries2); }); } break; } case MsgType.BoxState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br13 = Msg.Reader(msg.Payload)) { _boxes.ClientApply(BoxSync.ReadEntries(br13)); break; } } break; case MsgType.PopState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br9 = Msg.Reader(msg.Payload)) { _population.ClientApply(PopulationSync.Read(br9)); break; } } break; case MsgType.FurnitureOrder: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader binaryReader10 = Msg.Reader(msg.Payload)) { int num11 = binaryReader10.ReadInt32(); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(binaryReader10.ReadSingle(), binaryReader10.ReadSingle(), binaryReader10.ReadSingle()); Quaternion val3 = default(Quaternion); ((Quaternion)(ref val3))..ctor(binaryReader10.ReadSingle(), binaryReader10.ReadSingle(), binaryReader10.ReadSingle(), binaryReader10.ReadSingle()); string value2; string arg = (PeerNames.TryGetValue(msg.ConnId, out value2) ? value2 : "player"); CoopPlugin.Log.LogInfo((object)$"{arg} bought furniture: {(object)(EObjectType)num11}"); ShelfManager.SpawnInteractableObjectInPackageBox((EObjectType)num11, val2, val3); break; } } break; case MsgType.BoxRequest: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br3 = Msg.Reader(msg.Payload)) { _boxes.HostApplyRequest(BoxSync.ReadEntries(br3)); break; } } break; case MsgType.OrderRequest: { if (Role != CoopRole.Host || !InGameLevel()) { break; } using BinaryReader binaryReader2 = Msg.Reader(msg.Payload); int num = binaryReader2.ReadInt32(); bool flag = binaryReader2.ReadBoolean(); string rdName = binaryReader2.ReadString(); int num2 = binaryReader2.ReadInt32(); float cost = binaryReader2.ReadSingle(); string value; string text2 = (PeerNames.TryGetValue(msg.ConnId, out value) ? value : "player"); bool sizeDiffers; int num3 = ResolveRestockIndex(num, flag, rdName, out sizeDiffers); if (num3 >= 0) { CoopPlugin.Log.LogInfo((object)string.Format("{0} ordered {1} big={2} x{3} -> restock {4}{5}", text2, (object)(EItemType)num, flag, num2, num3, sizeDiffers ? " (size fallback)" : "")); RestockManager.SpawnPackageBoxItemMultipleFrame(num3, num2); if (sizeDiffers) { Send(msg.ConnId, MsgType.Toast, delegate(BinaryWriter bw) { bw.Write("'" + rdName + "' delivered in the host's box size (catalogs differ slightly)"); }); } break; } int num4 = 0; try { num4 = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList.Count; } catch { } CoopPlugin.Log.LogWarning((object)$"{text2} ordered unknown product type {num} '{rdName}' - refunding {cost:F0} (host catalog: {num4} products)"); LogCatalogCandidates(rdName); if (cost > 0f && cost < 100000f) { CEventManager.QueueEvent((CEvent)new CEventPlayer_AddCoin(cost, false)); } string reason = ((num4 <= 140) ? "the host's modded products haven't loaded yet (new save still in the tutorial?) - play past the host's tutorial and rejoin" : "match your content packs to order it"); Send(msg.ConnId, MsgType.Toast, delegate(BinaryWriter bw) { bw.Write($"'{rdName}' isn't in the host's catalog - refunded ${cost:F0}. Note: {reason}"); }); break; } case MsgType.Toast: if (Role == CoopRole.Client) { using (BinaryReader binaryReader29 = Msg.Reader(msg.Payload)) { RegisterLine = binaryReader29.ReadString(); RegisterLineTimer = 8f; break; } } break; case MsgType.CatalogDigest: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br27 = Msg.Reader(msg.Payload)) { CompareCatalogs(br27, msg.ConnId); break; } } break; case MsgType.BoxRemoved: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader binaryReader25 = Msg.Reader(msg.Payload)) { int num38 = binaryReader25.ReadInt32(); int num39 = binaryReader25.ReadInt32(); string value6; string arg2 = (PeerNames.TryGetValue(msg.ConnId, out value6) ? value6 : "player"); CoopPlugin.Log.LogInfo((object)$"{arg2} trashed box {num38} ({(object)(EItemType)num39})"); _boxes.HostApplyRemoval(num38, num39); break; } } break; case MsgType.LicenseUnlock: { if (!InGameLevel()) { break; } using BinaryReader binaryReader23 = Msg.Reader(msg.Payload); int itemType2 = binaryReader23.ReadInt32(); bool isBig = binaryReader23.ReadBoolean(); string rdName2 = binaryReader23.ReadString(); bool flag5 = ApplyLicenseUnlock(itemType2, isBig, rdName2); if (Role != CoopRole.Host) { break; } if (flag5) { Broadcast(MsgType.LicenseUnlock, delegate(BinaryWriter bw) { bw.Write(itemType2); bw.Write(isBig); bw.Write(rdName2); }); Send(msg.ConnId, MsgType.Toast, delegate(BinaryWriter bw) { bw.Write("license unlocked for everyone: " + rdName2); }); } else { Send(msg.ConnId, MsgType.Toast, delegate(BinaryWriter bw) { bw.Write("'" + rdName2 + "' license couldn't unlock on the host (product missing) - match your content packs"); }); } break; } case MsgType.LicenseState: { if (Role != CoopRole.Client || !InGameLevel()) { break; } using BinaryReader binaryReader20 = Msg.Reader(msg.Payload); bool scanner = binaryReader20.ReadBoolean(); int num30 = binaryReader20.ReadUInt16(); HashSet<long> wanted = new HashSet<long>(); for (int num31 = 0; num31 < num30; num31++) { int num32 = binaryReader20.ReadInt32(); bool flag4 = binaryReader20.ReadBoolean(); wanted.Add(((long)num32 << 1) | (flag4 ? 1 : 0)); } bool allowLock = Time.realtimeSinceStartupAsDouble - _lastLicenseBuyTime > 12.0; Guarded("license-apply", delegate { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 CPlayerData.m_IsScannerRestockUnlocked = CPlayerData.m_IsScannerRestockUnlocked || scanner; List<RestockData> restockDataList = CSingleton<InventoryBase>.Instance.m_StockItemData_SO.m_RestockDataList; List<bool> isItemLicenseUnlocked = CPlayerData.m_IsItemLicenseUnlocked; bool flag6 = false; for (int i = 0; i < restockDataList.Count && i < isItemLicenseUnlocked.Count; i++) { if (restockDataList[i] != null) { bool flag7 = wanted.Contains(((long)restockDataList[i].itemType << 1) | (restockDataList[i].isBigBox ? 1 : 0)); if (flag7 && !isItemLicenseUnlocked[i]) { GamePatches.ApplyingRemoteLicense = true; try { CPlayerData.SetUnlockItemLicense(i); } finally { GamePatches.ApplyingRemoteLicense = false; } flag6 = true; try { if ((int)restockDataList[i].itemType == 1) { TutorialManager.AddTaskValue((ETutorialTaskCondition)14, 1f); } } catch { } } else if (!flag7 && isItemLicenseUnlocked[i] && i != 0 && allowLock) { isItemLicenseUnlocked[i] = false; } } } if (flag6) { try { GameInstance.m_IsItemLicenseUnlocked = true; } catch { } RefreshLicensePanels(); } }); break; } case MsgType.StaffOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br19 = Msg.Reader(msg.Payload)) { _staff.HostApplyOp(br19); break; } } break; case MsgType.StaffState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br15 = Msg.Reader(msg.Payload)) { _staff.ClientApplyState(br15); break; } } break; case MsgType.ShopOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br14 = Msg.Reader(msg.Payload)) { _shopState.HostApplyOp(br14); break; } } break; case MsgType.ShopState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br11 = Msg.Reader(msg.Payload)) { _shopState.ClientApplyState(br11); break; } } break; case MsgType.SettingsOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br8 = Msg.Reader(msg.Payload)) { _settings.HostApplyOp(br8); break; } } break; case MsgType.SettingsState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br5 = Msg.Reader(msg.Payload)) { _settings.ClientApplyState(br5); break; } } break; case MsgType.MarketState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br4 = Msg.Reader(msg.Payload)) { _market.ClientApplyState(br4); break; } } break; case MsgType.ReportState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br2 = Msg.Reader(msg.Payload)) { _report.ClientApplyState(br2); break; } } break; case MsgType.ContainerOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br = Msg.Reader(msg.Payload)) { _containers.HostApplyOp(br); break; } } break; case MsgType.ContainerState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br30 = Msg.Reader(msg.Payload)) { _containers.ClientApplyState(br30); break; } } break; case MsgType.TournamentState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br28 = Msg.Reader(msg.Payload)) { _tournament.ClientApplyState(br28); break; } } break; case MsgType.CardBoxOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br26 = Msg.Reader(msg.Payload)) { _cardBoxes.HostApplyOp(br26); break; } } break; case MsgType.CardBoxState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br25 = Msg.Reader(msg.Payload)) { _cardBoxes.ClientApplyState(br25); break; } } break; case MsgType.EnumSync: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader24 = Msg.Reader(msg.Payload); int count3 = binaryReader24.ReadInt32(); byte[] hostBytes = Msg.Gunzip(binaryReader24.ReadBytes(count3)); if (CoopPlugin.AutoSyncCardDatabase.Value) { StatusLine = ModParity.InstallEnumFile(hostBytes); CoopPlugin.Log.LogInfo((object)("enum sync: " + StatusLine)); } else { StatusLine = "card databases differ - auto-sync is disabled; copy the host's enum_values.json (PrefabLoader folder) yourself"; } break; } case MsgType.GradingOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br23 = Msg.Reader(msg.Payload)) { _grading.HostApplyOp(br23); break; } } break; case MsgType.GradingState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br22 = Msg.Reader(msg.Payload)) { _grading.ClientApplyState(br22); break; } } break; case MsgType.TradeOp: if (Role == CoopRole.Host && InGameLevel()) { using (BinaryReader br20 = Msg.Reader(msg.Payload)) { _trades.HostApplyOp(br20); break; } } break; case MsgType.TradeState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br18 = Msg.Reader(msg.Payload)) { _trades.ClientApplyState(br18); break; } } break; case MsgType.TableState: if (Role == CoopRole.Client && InGameLevel()) { using (BinaryReader br16 = Msg.Reader(msg.Payload)) { _tables.ClientApplyState(br16); break; } } break; case MsgType.LightState: { if (Role != CoopRole.Client || !InGameLevel()) { break; } using BinaryReader binaryReader18 = Msg.Reader(msg.Payload); LightTimeData val5 = JsonUtility.FromJson<LightTimeData>(binaryReader18.ReadString()); if (val5 == null) { break; } try { if ((Object)(object)_lightManager == (Object)null) { _lightManager = Object.FindObjectOfType<LightManager>(); } if (!((Object)(object)_lightManager == (Object)null)) { int num21 = ((FiTimeOfDayIdx?.GetValue(_lightManager) is int num22) ? num22 : (-1)); int num23 = ((FiTimeHour?.GetValue(_lightManager) is int num24) ? num24 : (-1)); int num25 = ((FiTimeMin?.GetValue(_lightManager) is int num26) ? num26 : 0); int num27 = Math.Abs(val5.m_TimeHour * 60 + val5.m_TimeMin - (num23 * 60 + num25)); if (num21 != val5.m_TImeOfDayIndex || num27 > 4) { CPlayerData.m_LightTimeData = val5; FiFinishLoading?.SetValue(_lightManager, false); MiLightInit?.Invoke(_lightManager, null); CoopPlugin.Log.LogInfo((object)$"lighting re-synced (phase {num21}->{val5.m_TImeOfDayIndex}, drift {num27}min)"); } } break; } catch (Exception ex) { CoopPlugin.Log.LogWarning((object)("light apply: " + ex.Message)); break; } } case MsgType.ShopName: { if (Role != CoopRole.Client) { break; } using BinaryReader binaryReader16 = Msg.Reader(msg.Payload); string text5 = binaryReader16.Read