Beispiel #1
0
 internal static ulong GetManifestIDForDepot(uint DepotID)
 {
     lock (Lock)
     {
         ManualResetEvent Event = new ManualResetEvent(false);
         if (Depots is null)
         {
             Client.AppInfoReceived = (VDFStruct AppInfo) =>
             {
                 try { Depots = AppInfo["depots"]; }
                 catch { }
                 Event.Set();
             };
             Client.RequestAppInfo();
             Event.WaitOne(5000);
             Event.Close();
             if (Depots is null)
             {
                 Client.Disconnect();
                 return(0UL);
             }
         }
         try
         {
             ulong ManifestID = ulong.Parse(Depots[DepotID.ToString()]["manifests"]["public"].Value);
             Log($"Resolved latest manifest ID for depot {DepotID}: {ManifestID}");
             return(ManifestID);
         }
         catch { throw new ValidatorException("Failed to parse app info"); }
     }
 }
 private async void VerificationJob()
 {
     try
     {
         string ACFFile   = ACFPath;
         bool   ACFExists = Exists(ACFFile);
         if (ACF is null && ACFExists)
         {
             using (StreamReader Reader = new StreamReader(ACFFile))
                 ACF = new VDFStruct(Reader);
         }
         for (; ModIndex < Mods.Length; ModIndex++)
         {
             Dispatcher.Invoke(() => ModStatus.Text = string.Format(LocString(LocCode.MFVerifying), ModIndex + 1, Mods.Length, Mods[ModIndex].Name));
             ulong ID = Mods[ModIndex].ID, ManifestID = Downloader.UpdateMod(true, ID, ID);
             if (Finished)
             {
                 return;
             }
             if (await TryDeployAsync())
             {
                 await SteamAPI.SubscribeModAsync(ID);
             }
             if (!ACFExists)
             {
                 continue;
             }
             VDFStruct   ItemsInstalled = ACF["WorkshopItemsInstalled"], ItemDetails = ACF["WorkshopItemDetails"], IIEntry = ItemsInstalled?[ID.ToString()], IDEntry = ItemDetails?[ID.ToString()];
             ItemDetails Details = null;
             void GetItemDetails()
             {
                 if (!(Details is null))
                 {
                     return;
                 }
                 if (Connect())
                 {
                     List <ItemDetails> Response = GetDetails(ID);
                     if ((Response?.Count ?? 0) > 0)
                     {
                         Details = Response[0];
                     }
                 }
                 if (Details is null || Details.Result != 1)
                 {
                     throw new ValidatorException(LocString(LocCode.MIRequestFailed));
                 }
             }
             if (IIEntry is null)
             {
                 ACFChanged = true;
                 GetItemDetails();
                 IIEntry = new VDFStruct
                 {
                     Key      = ID.ToString(),
                     Children = new List <VDFStruct>
                     {
                         new VDFStruct {
                             Key = "size", Value = Details.Size.ToString()
                         },
                         new VDFStruct {
                             Key = "timeupdated", Value = Details.LastUpdated.ToString()
                         },
                         new VDFStruct {
                             Key = "manifest", Value = ManifestID.ToString()
                         }
                     }
                 };
                 if (ItemsInstalled != null)
                 {
                     ItemsInstalled.Children.Add(IIEntry);
                 }
             }
             else if (!ulong.TryParse(IIEntry["manifest"].Value, out ulong MID) || MID != ManifestID)
             {
                 ACFChanged = true;
                 GetItemDetails();
                 IIEntry["size"].Value        = Details.Size.ToString();
                 IIEntry["timeupdated"].Value = Details.LastUpdated.ToString();
                 IIEntry["manifest"].Value    = ManifestID.ToString();
             }
             if (IDEntry is null)
             {
                 ACFChanged = true;
                 GetItemDetails();
                 IDEntry = new VDFStruct
                 {
                     Key      = ID.ToString(),
                     Children = new List <VDFStruct>
                     {
                         new VDFStruct {
                             Key = "manifest", Value = ManifestID.ToString()
                         },
                         new VDFStruct {
                             Key = "timeupdated", Value = Details.LastUpdated.ToString()
                         },
                         new VDFStruct {
                             Key = "timetouched", Value = Now.ToUnixTimeSeconds().ToString()
                         },
                         new VDFStruct {
                             Key = "subscribedby", Value = Steam.ActiveUserID.ToString()
                         },
                     }
                 };
                 if (ItemDetails != null)
                 {
                     ItemDetails.Children.Add(IDEntry);
                 }
             }
             else if (!ulong.TryParse(IDEntry["manifest"].Value, out ulong MID) || MID != ManifestID)
             {
                 ACFChanged = true;
                 GetItemDetails();
                 IDEntry["manifest"].Value    = ManifestID.ToString();
                 IDEntry["timeupdated"].Value = Details.LastUpdated.ToString();
                 IDEntry["timetouched"].Value = Steam.ActiveUserID.ToString();
             }
         }
         await Dispatcher.Invoke(async() =>
         {
             Finished = true;
             TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
             ModStatus.Text = LocString(LocCode.MFVerificationComplete);
             if (ACFChanged)
             {
                 SetStatus(LocString(LocCode.MFApplyingModifications), YellowBrush);
                 if (!Steam.IsRunning)
                 {
                     using (StreamWriter Writer = new StreamWriter(ACFPath))
                         ACF.Write(Writer);
                 }
                 else if (ShowOptions("Info", LocString(LocCode.MFSteamRestartRequired)))
                 {
                     SetStatus(LocString(LocCode.WaitingForSteamShutdown), YellowBrush);
                     Retract();
                     Start($@"{Steam.Path}\Steam.exe", "-shutdown").WaitForExit();
                     while (Steam.IsRunning)
                     {
                         await Delay(1000);
                     }
                     using (StreamWriter Writer = new StreamWriter(ACFPath))
                         ACF.Write(Writer);
                     Start($@"{Steam.Path}\Steam.exe");
                 }
             }
             SetStatus(LocString(LocCode.MFSuccess), DarkGreen);
             Button.IsEnabled = false;
         });
     }
     catch (Exception Exception)
     {
         Downloader.ReleaseLock();
         if (Exception is AggregateException)
         {
             Exception = Exception.InnerException;
         }
         if (Exception is ValidatorException)
         {
             Dispatcher.Invoke(() =>
             {
                 SetStatus(string.Format(LocString(LocCode.ValidatorExc), Exception.Message), DarkRed);
                 FinishHandler();
             });
         }
         else
         {
             WriteAllText($@"{AppDataFolder}\LastCrash.txt", $"{Exception.Message}\n{Exception.StackTrace}");
             Dispatcher.Invoke(() =>
             {
                 new CrashWindow(Exception).ShowDialog();
                 Current.Shutdown();
             });
         }
         return;
     }
 }
Beispiel #3
0
        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);
        }