private bool ClientMessageReceivedHandler(byte[] Data, List <Action> Callbacks = null) { MessageType Type = GetMessageType(Data); if (Type == MessageType.Invalid) { Disconnect(false); return(false); } switch (Type) { case MessageType.Multi: { Message <Multi> Message = new Message <Multi>(Data); byte[] Payload = Message.Body.MessageBody; if ((Message.Body.UncompressedSize ?? 0) > 0) { byte[] DecompressedPayload; int UncompressedSize = Message.Body.UncompressedSize.Value; try { using (MemoryStream Stream = new MemoryStream(Payload)) using (GZipStream Decompressor = new GZipStream(Stream, CompressionMode.Decompress)) Decompressor.Read(DecompressedPayload = new byte[UncompressedSize], 0, UncompressedSize); Payload = DecompressedPayload; } catch { break; } } List <Action> CallbacksList = new List <Action>(); using (MemoryStream Stream = new MemoryStream(Payload)) using (BinaryReader Reader = new BinaryReader(Stream)) while (Stream.Position != Stream.Length) { byte[] Buffer = new byte[4]; Stream.Read(Buffer, 0, 4); int PacketSize = ToInt32(Buffer, 0); Buffer = new byte[PacketSize]; Stream.Read(Buffer, 0, PacketSize); if (!ClientMessageReceivedHandler(Buffer, CallbacksList)) { break; } } foreach (Action Callback in CallbacksList) { Callback(); } break; } case MessageType.LogOnResponse: { Message <LogOn> Message = new Message <LogOn>(Data); int Result = Message.Body.Result; Log($"Received log on response, result code: {Result}"); if (Result == 1) { IsLogged = true; SessionID = Message.Header.SessionID; SteamID = Message.Header.SteamID; HeartbeatTimer.Change(0, Message.Body.HeartbeatDelay * 1000); Log($"Log on succeeded, initiating heartbeat with {Message.Body.HeartbeatDelay} seconds delay"); } if (Callbacks is null) { LoggedOn?.Invoke(); } else { Callbacks.Add(() => LoggedOn?.Invoke()); } break; } case MessageType.ServiceMethodResponse: { byte[] SerializedMethod = new Message <ServiceMethod>(Data).Body.SerializedMethod; switch (ExpectedServiceMethod) { case 0: { ItemInfo Info = new ItemInfo(); Info.Deserialize(SerializedMethod); WorkshopItem Item = Info.Item; ulong ManifestID = Item.ManifestID; Log($"Received latest manifest ID for mod {Item.ItemID}: {ManifestID}"); if (Callbacks is null) { ModInfoReceived(ManifestID); } else { Callbacks.Add(() => ModInfoReceived(ManifestID)); } break; } case 1: { GetDetails Details = new GetDetails(); Details.Deserialize(SerializedMethod); Log("Received mods details"); if (Callbacks is null) { ModsDetailsReceived(Details.Details); } else { Callbacks.Add(() => ModsDetailsReceived(Details.Details)); } break; } case 2: { QueryFiles Query = new QueryFiles(); Query.Deserialize(SerializedMethod); Log($"Received {Query.Details.Count} queried items details"); if (Callbacks is null) { QueryReceived(Query.Details, Query.Total); } else { Callbacks.Add(() => QueryReceived(Query.Details, Query.Total)); } break; } } break; } case MessageType.ProductInfoResponse: { Message <ProductInfo> Message = new Message <ProductInfo>(Data); if (Message.Body.App is null) { break; } Log("Received product info for app 346110"); VDFStruct AppInfo; using (MemoryStream Stream = new MemoryStream(Message.Body.App.Buffer)) using (StreamReader Reader = new StreamReader(Stream)) AppInfo = new VDFStruct(Reader); if (Callbacks is null) { AppInfoReceived(AppInfo); } else { Callbacks.Add(() => AppInfoReceived(AppInfo)); } break; } } return(true); }