Example #1
0
        internal static AddonInfo ReadAddonInfo(BinaryReader reader, char gmadFormatVersion)
        {
            ulong steamid   = reader.ReadUInt64();           //steamid
            ulong timestamp = reader.ReadUInt64();           //timestamp

            var timeUpdated = new EpochTime(( int )timestamp).DateTime;

            if (gmadFormatVersion > 1)
            {
                string content = reader.ReadBootilString();
                while (!string.IsNullOrEmpty(content))
                {
                    content = reader.ReadBootilString();
                }
            }

            string gmadTitle     = reader.ReadBootilString();
            string gmadAddonJson = reader.ReadBootilString();             //gmad reads this first then parses it later to get the actual description
            string gmadAuthor    = reader.ReadBootilString();

            int gmadAddonVersion = reader.ReadInt32();

            AddonInfo addonInfo = DeserializeAddonInfoCallback(gmadAddonJson);

            addonInfo.Title = gmadTitle;

            return(addonInfo);
        }
Example #2
0
 private static string CreateJsonDescription(AddonInfo addonInfo)
 {
     return(SerializeAddonInfoToStringCallback(new AddonInfo()
     {
         Description = addonInfo.Description,
         Tags = addonInfo.Tags,
         WorkshopType = addonInfo.WorkshopType
     }));
 }
Example #3
0
 internal static void WriteAddonInfo(BinaryWriter writer, AddonInfo addonInfo, DateTime timestamp)
 {
     writer.Write(( ulong )0);               //unused steamid
     writer.Write(( ulong )timestamp.ToEpochTimestamp());
     writer.Write(( char )0);                //required content, this hasn't been worked on and I doubt it will
     writer.WriteBootilString(addonInfo.Title);
     writer.WriteBootilString(CreateJsonDescription(addonInfo));
     writer.WriteBootilString("Author Name"); //unused author name
     writer.Write(1);                         //unused addon version
 }
Example #4
0
 private static void PopulateOldAddonInfo(AddonInfo addonInfo, AddonInfo newAddonInfo)
 {
     //populate tags description and type only
     addonInfo.Description  = newAddonInfo.Description;
     addonInfo.WorkshopType = newAddonInfo.WorkshopType;
     if (addonInfo.Tags != null)
     {
         addonInfo.Tags.UnionWith(newAddonInfo.Tags);
     }
     else
     {
         addonInfo.Tags = new HashSet <string>(newAddonInfo.Tags);
     }
 }
Example #5
0
        /// <summary>
        /// Extract the given GMA inputstream
        /// </summary>
        /// <param name="inputStream">the raw stream of the gma</param>
        /// <param name="requestFileStream">the callback to write the output file to, return a null if the path is invalid</param>
        /// <param name="addonInfo"> the addon info object to feed info to, saving this is at your discretion</param>
        /// <returns></returns>
        public static async Task <bool> Extract(Stream inputStream, Func <string, Stream> requestFileStream, AddonInfo addonInfo)
        {
            inputStream.Position = 0;

            using (BinaryReader reader = new BinaryReader(inputStream))
            {
                var(gmadIdent, gmadFormatVersion) = ReadHeader(reader);

                if (!gmadIdent.SequenceEqual(Ident) || gmadFormatVersion > Version)
                {
                    return(false);
                }

                AddonInfo newAddonInfo = ReadAddonInfo(reader, gmadFormatVersion);

                //the term populate here is correct, we don't want to override it again as the object might be one
                //passed from an existing file already

                PopulateOldAddonInfo(addonInfo, newAddonInfo);

                long gmadFileblock = ReadFileList(reader, out var gmadFileEntries);
                int  badFileCount  = 0;

                foreach (var entry in gmadFileEntries)
                {
                    var stream = requestFileStream(entry.Name);

                    if (stream is null)
                    {
                        stream = requestFileStream($"badnames/{badFileCount}+.unk");
                        badFileCount++;
                    }

                    if (stream != null)
                    {
                        inputStream.Position = gmadFileblock + entry.Offset;
                        await inputStream.CopyToLimitedAsync(stream, entry.Size);
                    }
                }

                uint addoncrc = reader.ReadUInt32();                 //not used during the extraction of gmas
            }


            return(true);
        }
Example #6
0
        public static async Task <bool> Create(Dictionary <string, Stream> files, Stream outputStream, AddonInfo addonInfo)
        {
            var orderedFiles = files.OrderBy(kv => kv.Key);

            using (BinaryWriter buffer = new BinaryWriter(outputStream))
            {
                WriteHeader(buffer);
                WriteAddonInfo(buffer, addonInfo, DateTime.Now);
                await WriteFiles(buffer, outputStream, orderedFiles);

                //don't write CRC32 as it's not used anywhere
                buffer.Write(( uint )0);
            }

            return(true);
        }