/// <summary>
        /// Loads the given file specified by PackagePath and
        /// returns the serialized UnrealPackage.
        /// </summary>
        public static UnrealPackage LoadPackage(string packagePath, FileAccess fileAccess = FileAccess.Read)
        {
            var packageName = Path.GetFileNameWithoutExtension(packagePath);

            UPackageStream stream;

            if (packageName.EndsWith("_decrypted"))
            {
                stream = new UPackageStream(packagePath, FileMode.Open, fileAccess);
                Log.Info("Loading decrypted RL package");
            }
            else
            {
                try
                {
                    stream = new RLPackageStream(packagePath);
                    Log.Info("Loading encrypted RL package");
                }
                catch (InvalidDataException e)
                {
                    stream          = new UPackageStream(packagePath, FileMode.Open, fileAccess);
                    stream.Position = 0;
                }
            }
            var package = new UnrealPackage(stream);

            package.Deserialize(stream);
            return(package);
        }
 /// <summary>
 /// Loads the given file specified by PackagePath and
 /// returns the serialized UnrealPackage.
 /// </summary>
 public static UnrealPackage LoadPackage( string packagePath, IBufferDecoder decoder = null, FileAccess fileAccess = FileAccess.Read )
 {
     var stream = new UPackageStream( packagePath, FileMode.Open, fileAccess );
     var package = new UnrealPackage( stream ) {Decoder = decoder};
     package.Deserialize( stream );
     return package;
 }
        /// <summary>
        /// Loads the given file specified by PackagePath and
        /// returns the serialized UnrealPackage.
        /// </summary>
        public static UnrealPackage LoadPackage(string packagePath, FileAccess fileAccess = FileAccess.Read)
        {
            var stream  = new UPackageStream(packagePath, FileMode.Open, fileAccess);
            var package = new UnrealPackage(stream);

            package.Deserialize(stream);
            return(package);
        }
        public void Decompress( UPackageStream inStream, UPackageStream outStream )
        {
            inStream.Seek( CompressedOffset, System.IO.SeekOrigin.Begin );
            _Header.Deserialize( inStream );

            outStream.Seek( UncompressedOffset, System.IO.SeekOrigin.Begin );
            foreach( var buffer in _Header.Blocks.Select( block => block.Decompress() ) )
            {
                outStream.Write( buffer, 0, buffer.Length );
            }
        }
        public void Decompress(UPackageStream inStream, UPackageStream outStream)
        {
            inStream.Seek(CompressedOffset, System.IO.SeekOrigin.Begin);
            _Header.Deserialize(inStream);

            outStream.Seek(UncompressedOffset, System.IO.SeekOrigin.Begin);
            foreach (var buffer in _Header.Blocks.Select(block => block.Decompress()))
            {
                outStream.Write(buffer, 0, buffer.Length);
            }
        }
        /// <summary>
        /// Loads the given file specified by PackagePath and
        /// returns the serialized UnrealPackage.
        /// </summary>
        public static UnrealPackage LoadPackage(string packagePath, FileAccess fileAccess = FileAccess.Read)
        {
            var packageName = Path.GetFileNameWithoutExtension(packagePath);

            UPackageStream stream;

            if (packageName.EndsWith("_decrypted"))
            {
                stream = new UPackageStream(packagePath, FileMode.Open, fileAccess);
                Log.Info("Loading decrypted RL package");
            }
            else
            {
                try
                {
                    var rlStream = new RLPackageStream(packagePath);
                    if (rlStream.decryptionState == RLUPKT.Core.DecryptionState.Success)
                    {
                        stream = rlStream;
                    }
                    else
                    {
                        return(null);
                    }

                    Log.Info("Loading encrypted RL package");
                }
                catch (InvalidDataException e)
                {
                    stream = new UPackageStream(packagePath, FileMode.Open, fileAccess)
                    {
                        Position = 0
                    };
                }
            }

            var package = new UnrealPackage(stream);

            package.Deserialize(stream);

            FullyLoadImportPackages(package, Path.GetDirectoryName(packagePath));
            Log.Info($"[LoadPackage] done Loading {packageName}");
            return(package);
        }
        /// <summary>
        /// Creates a new instance of the UELib.UnrealPackage class with a PackageStream and name.
        /// </summary>
        /// <param name="stream">A loaded UELib.PackageStream.</param>
        public UnrealPackage( UPackageStream stream )
        {
            _FullPackageName = stream.Name;
            Stream = stream;
            Stream.PostInit( this );

            // File Type
            // Signature is tested in UPackageStream
            IsBigEndianEncoded = stream.BigEndianCode;
        }
        public void Deserialize( UPackageStream stream )
        {
            // Read as one variable due Big Endian Encoding.
            Version = stream.ReadUInt32();
            LicenseeVersion = (ushort)(Version >> 16);
            Version = (Version & 0xFFFFU);
            Console.WriteLine( "\tPackage Version:" + Version + "/" + LicenseeVersion );

            Build = new GameBuild( this );
            Console.WriteLine( "\tBuild:" + Build.Name );

            stream.BuildDetected( Build );

            if( Version >= VHeaderSize )
            {
#if BIOSHOCK
                if( Build == GameBuild.BuildName.Bioshock_Infinite )
                {
                    var unk = stream.ReadInt32();
                }
#endif
#if MKKE
                if( Build == GameBuild.BuildName.MKKE )
                {
                    stream.Skip( 8 );
                }
#endif
#if TRANSFORMERS
                if( Build == GameBuild.BuildName.Transformers && LicenseeVersion >= 55 )
                {
                    if( LicenseeVersion >= 181 )
                    {
                        stream.Skip( 16 );
                    }
                    stream.Skip( 4 );
                }
#endif
                // Offset to the first class(not object) in the package.
                HeaderSize = stream.ReadUInt32();
                Console.WriteLine( "\tHeader Size: " + HeaderSize );
                if( Version >= VGroup )
                {
                    // UPK content category e.g. Weapons, Sounds or Meshes.
                    Group = stream.ReadText();
                }
            }

            // Bitflags such as AllowDownload.
            PackageFlags = stream.ReadUInt32();
            Console.WriteLine( "\tPackage Flags:" + PackageFlags );

            // Summary data such as ObjectCount.
            _TablesData = new TablesData();
            _TablesData.Deserialize( stream );
            if( Version < 68 )
            {
                int heritageCount = stream.ReadInt32();
                int heritageOffset = stream.ReadInt32();

                stream.Seek( heritageOffset, SeekOrigin.Begin );
                _Heritages = new List<ushort>( heritageCount );
                for( var i = 0; i < heritageCount; ++ i )
                {
                    _Heritages.Add( stream.ReadUShort() );
                }
            }
            else
            {
#if THIEFDEADLYSHADOWS
                if( Build == GameBuild.BuildName.Thief_DS )
                {
                    stream.Skip( 4 );
                }
#endif
#if BORDERLANDS
                if( Build == GameBuild.BuildName.Borderlands )
                {
                    stream.Skip( 4 );
                }
#endif
#if MKKE
                if( Build == GameBuild.BuildName.MKKE )
                {
                    stream.Skip( 4 );
                }
#endif
                GUID = stream.ReadGuid();
                Console.Write( "\r\n\tGUID:" + GUID + "\r\n" );
#if TERA
                if( Build == GameBuild.BuildName.Tera )
                {
                    stream.Position -= 4;
                }
#endif
#if MKKE
                if( Build != GameBuild.BuildName.MKKE )
                {
#endif
                int generationCount = stream.ReadInt32();
                Generations = new UArray<UGenerationTableItem>( stream, generationCount );
                Console.WriteLine( "Deserialized {0} generations", Generations.Count );
#if MKKE
                }
#endif
#if TERA
                if( Build == GameBuild.BuildName.Tera )
                {
                    _TablesData.NamesCount = (uint)Generations.Last().NamesCount;
                }
#endif
                if( Version >= VEngineVersion )
                {
                    // The Engine Version this package was created with
                    EngineVersion = stream.ReadInt32();
                    Console.WriteLine( "\tEngineVersion:" + EngineVersion );
                    if( Version >= VCOOKEDPACKAGES )
                    {
                        // The Cooker Version this package was cooked with
                        CookerVersion = stream.ReadInt32();
                        Console.WriteLine( "\tCookerVersion:" + CookerVersion );

                        // Read compressed info?
                        if( Version >= VCompression )
                        {
                            if( IsCooked() )
                            {
                                CompressionFlags = stream.ReadUInt32();
                                Console.WriteLine( "\tCompressionFlags:" + CompressionFlags );
                                CompressedChunks = new UArray<CompressedChunk>{Capacity = stream.ReadInt32()};
                                //long uncookedSize = stream.Position;
                                if( CompressedChunks.Capacity > 0 )
                                {
                                    CompressedChunks.Deserialize( stream, CompressedChunks.Capacity );
                                    return;

                                    //try
                                    //{
                                    //    UPackageStream outStream = new UPackageStream( packagePath + ".dec", System.IO.FileMode.Create, FileAccess.ReadWrite );
                                    //    //File.SetAttributes( packagePath + ".dec", FileAttributes.Temporary );
                                    //    outStream.Package = pkg;
                                    //    outStream._BigEndianCode = stream._BigEndianCode;

                                    //    var headerBytes = new byte[uncookedSize];
                                    //    stream.Seek( 0, SeekOrigin.Begin );
                                    //    stream.Read( headerBytes, 0, (int)uncookedSize );
                                    //    outStream.Write( headerBytes, 0, (int)uncookedSize );
                                    //    foreach( var chunk in pkg.CompressedChunks )
                                    //    {
                                    //        chunk.Decompress( stream, outStream );
                                    //    }
                                    //    outStream.Flush();
                                    //    pkg.Stream = outStream;
                                    //    stream = outStream;
                                    //    return pkg;
                                    //}
                                    //catch( Exception e )
                                    //{
                                    //    throw new DecompressPackageException();
                                    //}
                                }
                            }
                        }
                    }
                }
            }

            // Read the name table
            if( _TablesData.NamesCount > 0 )
            {
                Console.WriteLine( "P: " + stream.Position + " NP: " + _TablesData.NamesOffset );

                stream.Seek( _TablesData.NamesOffset, SeekOrigin.Begin );
                Names = new List<UNameTableItem>( (int)_TablesData.NamesCount );
                for( var i = 0; i < _TablesData.NamesCount; ++ i )
                {
                    var nameEntry = new UNameTableItem{Offset = (int)stream.Position, Index = i};
                    nameEntry.Deserialize( stream );
                    nameEntry.Size = (int)(stream.Position - nameEntry.Offset);
                    Names.Add( nameEntry );
                }
                Console.WriteLine( "Deserialized {0} names", Names.Count );
            }

            // Read Import Table
            if( _TablesData.ImportsCount > 0 )
            {
                Console.WriteLine( "P: " + stream.Position + " IP: " + _TablesData.ImportsOffset );

                stream.Seek( _TablesData.ImportsOffset, SeekOrigin.Begin );
                Imports = new List<UImportTableItem>( (int)_TablesData.ImportsCount );
                for( var i = 0; i < _TablesData.ImportsCount; ++ i )
                {
                    var imp = new UImportTableItem{Offset = (int)stream.Position, Index = i, Owner = this};
                    imp.Deserialize( stream );
                    imp.Size = (int)(stream.Position - imp.Offset);
                    Imports.Add( imp );
                }
                Console.WriteLine( "Deserialized {0} imports", Imports.Count );
            }

            // Read Export Table
            if( _TablesData.ExportsCount > 0 )
            {
                Console.WriteLine( "P: " + stream.Position + " EP: " + _TablesData.ExportsOffset );

                stream.Seek( _TablesData.ExportsOffset, SeekOrigin.Begin );
                Exports = new List<UExportTableItem>( (int)_TablesData.ExportsCount );
                for( var i = 0; i < _TablesData.ExportsCount; ++ i )
                {
                    var exp = new UExportTableItem{Offset = (int)stream.Position, Index = i, Owner = this};
                    // For the GetObjectName like functions
                    try
                    {
                        exp.Deserialize( stream );
                    }
                    catch
                    {
                        Console.WriteLine( "Failed to deserialize export object at index:" + i );
                        break;
                    }
                    finally
                    {
                        exp.Size = (int)(stream.Position - exp.Offset);
                        Exports.Add( exp );
                    }
                }
                Console.WriteLine( "Deserialized {0} exports", Exports.Count );
            }

            /*if( pkg.Data.DependsOffset > 0 )
            {
                stream.Seek( pkg.Data.DependsOffset, SeekOrigin.Begin );
                pkg._DependsTableList = new List<UnrealDependsTable>( (int)pkg.Data.DependsCount );
                for( var i = 0; i < pkg.Data.DependsCount; ++ i )
                {
                    var dep = new UnrealDependsTable{TableOffset = stream.Position, TableIndex = i, Owner = pkg};
                    dep.Deserialize( stream );
                    dep.TableSize = (int)(stream.Position - dep.TableOffset);
                    pkg.DependsTableList.Add( dep );
                }
                Console.WriteLine( "Deserialized {0} dependencies", pkg.DependsTableList.Count );
            }*/

            HeaderSize = stream.Position;
        }
 public static UnrealPackage DeserializePackage( string packagePath, FileAccess fileAccess = FileAccess.Read )
 {
     var stream = new UPackageStream( packagePath, FileMode.Open, fileAccess );
     var pkg = new UnrealPackage( stream );
     pkg.Deserialize( stream );
     return pkg;
 }