示例#1
0
        public void TestFileStreamRebuildWad()
        {
            WadBuilder wadBuilder = new WadBuilder();

            // Build entries
            foreach (WadEntry entry in this._originalWad.Entries.Values)
            {
                WadEntryBuilder entryBuilder            = new WadEntryBuilder(entry.ChecksumType);
                Stream          entryDecompressedStream = entry.GetDataHandle().GetDecompressedStream();
                string          entryFileName           = "temp/" + entry.XXHash + "." + Utilities.GetExtension(Utilities.GetExtensionType(entryDecompressedStream));

                // Extract entry data to temporary file
                using (FileStream writeEntryFileStream = File.OpenWrite(entryFileName))
                {
                    entry.GetDataHandle().GetDecompressedStream().CopyTo(writeEntryFileStream);
                }

                entryBuilder
                .WithPathXXHash(entry.XXHash)
                .WithFileDataStream(entryFileName);

                wadBuilder.WithEntry(entryBuilder);
            }

            MemoryStream rebuiltWadStream = new MemoryStream();

            Assert.DoesNotThrow(delegate
            {
                wadBuilder.Build(rebuiltWadStream, true);
            }, "Failed to build WAD using files");

            rebuiltWadStream.Seek(0, SeekOrigin.Begin);
            this._fileStreamWad = Wad.Mount(rebuiltWadStream, true);
        }
示例#2
0
        public static WadBuilder Merge(WadBuilder wadBase, WadBuilder wadToMerge)
        {
            WadBuilder wadBuilder = new WadBuilder();

            // First add new files and then modify changed ones
            foreach (var entryToMerge in wadToMerge.Entries)
            {
                // Add new entry
                if (wadBase.Entries.ContainsKey(entryToMerge.Key) is false)
                {
                    wadBuilder.WithEntry(entryToMerge.Value);
                }
                // Modify existing entry
                else if (!entryToMerge.Value.Sha256Checksum.SequenceEqual(wadBase.Entries[entryToMerge.Key].Sha256Checksum))
                {
                    wadBuilder.WithEntry(entryToMerge.Value);
                }
            }

            // Copy over the rest
            foreach (var entry in wadBase.Entries.Where(x => wadToMerge.Entries.ContainsKey(x.Key) is false))
            {
                wadBuilder.WithEntry(entry.Value);
            }

            return(wadBuilder);
        }
示例#3
0
        private void PackWadFolder(string wadFolderLocation)
        {
            string[] wadFolderFiles = Directory.GetFiles(wadFolderLocation, "*", SearchOption.AllDirectories);
            if (wadFolderFiles.Length > 0)
            {
                char   separator = Pathing.GetPathSeparator(wadFolderLocation);
                string wadName   = wadFolderLocation.Split(separator).Last();

                WadBuilder wad = new WadBuilder();

                //Add each file to the WAD
                foreach (string wadFolderFile in Directory.EnumerateFiles(wadFolderLocation, "*", SearchOption.AllDirectories))
                {
                    string path = wadFolderFile.Replace(wadFolderLocation + separator, "").Replace('\\', '/');
                    ulong  hash = XXHash.XXH64(Encoding.ASCII.GetBytes(path.ToLower()));

                    WadEntryBuilder entryBuilder = new();

                    entryBuilder
                    .WithPathXXHash(hash)
                    .WithFileDataStream(File.OpenRead(wadFolderFile));

                    wad.WithEntry(entryBuilder);
                }

                //After WAD creation is finished we can write the WAD to the ZIP
                ZipArchiveEntry archiveEntry = this.Content.CreateEntry(string.Format("WAD/{0}", wadName));
                wad.Build(archiveEntry.Open(), false);
            }
        }
示例#4
0
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        WadBuilder wadBuilder = (WadBuilder)target;

        if (GUILayout.Button("Load and Build Wad Map"))
        {
            wadBuilder.LoadAndBuildMap();
        }
    }
示例#5
0
        public void TestDataStreamRebuildWad()
        {
            WadBuilder wadBuilder = new WadBuilder();

            // Build entries
            foreach (WadEntry entry in this._originalWad.Entries.Values)
            {
                WadEntryBuilder entryBuilder = new WadEntryBuilder(entry.ChecksumType);

                entryBuilder
                .WithPathXXHash(entry.XXHash);

                if (entry.Type == WadEntryType.GZipCompressed)
                {
                    entryBuilder.WithGZipDataStream(entry.GetDataHandle().GetCompressedStream(), entry.CompressedSize, entry.UncompressedSize);
                }
                else if (entry.Type == WadEntryType.ZStandardCompressed)
                {
                    entryBuilder.WithZstdDataStream(entry.GetDataHandle().GetCompressedStream(), entry.CompressedSize, entry.UncompressedSize);
                }
                else if (entry.Type == WadEntryType.Uncompressed)
                {
                    entryBuilder.WithUncompressedDataStream(entry.GetDataHandle().GetDecompressedStream());
                }
                else if (entry.Type == WadEntryType.FileRedirection)
                {
                    entryBuilder.WithFileRedirection(entry.FileRedirection);
                }

                wadBuilder.WithEntry(entryBuilder);
            }

            MemoryStream rebuiltWadStream = new MemoryStream();

            Assert.DoesNotThrow(delegate
            {
                wadBuilder.Build(rebuiltWadStream, true);
            }, "Failed to build WAD using data streams");

            rebuiltWadStream.Seek(0, SeekOrigin.Begin);
            this._dataStreamWad = Wad.Mount(rebuiltWadStream, true);
        }
示例#6
0
        public void UninstallMod(ModFile mod)
        {
            Log.Information("Uninstalling Mod: " + mod.GetID());
            List <ulong> moddedEntries = new List <ulong>();

            if (this.Index.ModEntryMap.TryGetValue(mod.GetID(), out List <ulong> _moddedEntries))
            {
                moddedEntries = new List <ulong>(_moddedEntries);
            }
            Dictionary <string, WadBuilder> moddedWads = new Dictionary <string, WadBuilder>();

            this.Index.StartEdit();

            //In this loop we remove the installed WAD entries
            foreach (ulong moddedEntry in moddedEntries)
            {
                List <string> moddedEntryWadFiles = this.Index.Mod[moddedEntry];

                //Initialize WAD files for entry deletion
                foreach (string moddedEntryWadFile in moddedEntryWadFiles)
                {
                    if (!moddedWads.ContainsKey(moddedEntryWadFile))
                    {
                        using Wad moddedWad = Wad.Mount(string.Format(@"{0}\{1}", OVERLAY_FOLDER, moddedEntryWadFile), false);
                        moddedWads.Add(moddedEntryWadFile, new WadBuilder(moddedWad));
                    }

                    moddedWads[moddedEntryWadFile].RemoveEntry(moddedEntry);
                }

                this.Index.RemoveModdedEntry(moddedEntry, mod.GetID());
            }

            //Now we need to either delete empty WAD files or fill the ones from which we removed the entries with original files
            //if the modified ones are the same as original then we need to delete those too
            foreach (KeyValuePair <string, WadBuilder> moddedWad in moddedWads)
            {
                //If the WAD isn't being used by any other mod or is empty we can delete it
                if (this.Index.WadModMap[moddedWad.Key].All(x => x == mod.GetID()) ||
                    moddedWad.Value.Entries.Count == 0)
                {
                    File.Delete(string.Format(@"{0}\{1}", OVERLAY_FOLDER, moddedWad.Key));
                }
                //If it's used by some other mods we need to merge it into the original WAD
                else
                {
                    string gameWadPath    = string.Format(@"{0}\{1}", this.LeagueFolder, moddedWad.Key);
                    string overlayWadPath = string.Format(@"{0}\{1}", OVERLAY_FOLDER, moddedWad.Key);
                    using Wad originalWad = Wad.Mount(gameWadPath, false);

                    WadBuilder mergedWad = WadMerger.Merge(new WadBuilder(originalWad), moddedWad.Value);
                    mergedWad.Build(overlayWadPath + ".temp");

                    File.Delete(overlayWadPath);
                    File.Move(overlayWadPath + ".temp", overlayWadPath);
                }
            }

            this.Database.ChangeModState(mod.GetID(), false);
            this.Index.RemoveMod(mod.GetID());
            this.Index.EndEdit();
        }
示例#7
0
        private void WriteModWADFiles(ModFile mod)
        {
            Action <KeyValuePair <string, WadBuilder> > writeWadFileDelegate = new (WriteWadFile);

            if (Config.Get <bool>("ParallelWadInstallation"))
            {
                ParallelOptions parallelOptions = new ParallelOptions()
                {
                    MaxDegreeOfParallelism = Environment.ProcessorCount
                };

                Parallel.ForEach(mod.GetWadFiles(this.Index), parallelOptions, (modWadFile) =>
                {
                    writeWadFileDelegate.Invoke(modWadFile);
                });
            }
            else
            {
                var modWadFiles = mod.GetWadFiles(this.Index);

                foreach (var modWadFile in modWadFiles)
                {
                    writeWadFileDelegate.Invoke(modWadFile);
                }

                foreach (var modWadFile in modWadFiles)
                {
                    modWadFile.Value.Dispose();
                }
            }

            void WriteWadFile(KeyValuePair <string, WadBuilder> modWadFile)
            {
                string wadPath           = this.Index.FindWADPath(modWadFile.Key);
                string overlayModWadPath = string.Format(@"{0}\{1}", OVERLAY_FOLDER, wadPath);
                string gameModWadPath    = string.Format(@"{0}\{1}", this.LeagueFolder, wadPath);

                //Check if the WAD already exists, if it does, we need to merge the 2 WADs
                //if it doesnt, then we need to copy it from the game directory
                if (!File.Exists(overlayModWadPath))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(overlayModWadPath));

                    using (Wad baseWad = Wad.Mount(gameModWadPath, false))
                    {
                        WadBuilder mergedWad = WadMerger.Merge(new WadBuilder(baseWad), modWadFile.Value);
                        mergedWad.Build(overlayModWadPath);
                    }
                }
                else
                {
                    File.Move(overlayModWadPath, overlayModWadPath + ".temp");

                    using (Wad mergedWad = Wad.Mount(overlayModWadPath + ".temp", false))
                    {
                        WadBuilder mergedWadBuilder = WadMerger.Merge(new WadBuilder(mergedWad), modWadFile.Value);
                        mergedWadBuilder.Build(overlayModWadPath);
                    }

                    //Delete temp wad file
                    File.Delete(overlayModWadPath + ".temp");
                }
            }
        }