Пример #1
0
        private void DoExtractHandler(object sender, DoWorkEventArgs e)
        {
            extractProgress = 0;
            if (fileNodeList.Count > 0)
            {
                FileNode rootnode = fileNodeList[0];
                totalProgress = rootnode.getSelectedCount();
                SetProgressbarMax(totalProgress);
                SetProgressbar(0, totalProgress);
            }
            if (totalProgress == 0)
            {
                if (!CNMode)
                {
                    PrintLog("Nothing selected.");
                }
                else
                {
                    PrintLog("未选择任何文件");
                }
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    ExtractBtn.IsEnabled     = true;
                    RegExCheckBox.IsEnabled  = true;
                    FilterBox.IsEnabled      = true;
                    ApplyFilterBtn.IsEnabled = true;
                    PauseBtn.Visibility      = Visibility.Hidden;
                    TerminateBtn.Visibility  = Visibility.Hidden;
                }));
                return;
            }
            if (!CNMode)
            {
                PrintLog("Export to: " + outputDirectory, true);
                PrintLog("It may take a long time to extract all the files you selected which depends on the file size and amount you selected.");
            }
            else
            {
                PrintLog("解包至: " + outputDirectory, true);
                PrintLog("根据你所选取的文件数量和大小,这可能会花费很长时间,请耐心等待");
            }
            int failed = 0;

            if (mergeChecked)
            {
                chunkMap.FirstOrDefault().Value.ExtractSelected(fileNodeList, outputDirectory, this);
            }
            else
            {
                failed = mainChunk.ExtractSelected(fileNodeList, outputDirectory, this);
            }
            if (failed > 0)
            {
                if (!CNMode)
                {
                    PrintLog($"{failed} files failed to extract in total.");
                }
                else
                {
                    PrintLog($"总计{failed}个文件提取失败");
                }
            }
            Dispatcher.BeginInvoke(new Action(() =>
            {
                ExtractBtn.IsEnabled     = true;
                RegExCheckBox.IsEnabled  = true;
                FilterBox.IsEnabled      = true;
                ApplyFilterBtn.IsEnabled = true;
                PauseBtn.Visibility      = Visibility.Hidden;
                TerminateBtn.Visibility  = Visibility.Hidden;
                PauseBtn.Background      = System.Windows.Media.Brushes.Orange;
                PauseBtn.Content         = CNMode ? "暂停" : "Pause";
                terminateFlag            = false;
                pauseFlag = false;
            }));
            if (!CNMode)
            {
                PrintLog("Finished!");
            }
            else
            {
                PrintLog("提取完成!");
            }
        }
Пример #2
0
        // Learns from WorldChunkTool by MHVuze https://github.com/mhvuze/WorldChunkTool
        public List <FileNode> AnalyzeChunk(String FileInput, MainWindow mainwindow, List <FileNode> inputFileList)
        {
            bindingWindow = mainwindow;
            fileinput     = FileInput;
            FileInfo fileinputInfo = new FileInfo(fileinput);

            if (!MainWindow.CNMode)
            {
                mainwindow.printlog($"Now analyzing {fileinputInfo.Name}");
            }
            else
            {
                mainwindow.printlog($"正在解析 {fileinputInfo.Name}");
            }
            ChunkCache = new Dictionary <int, byte[]>();

            List <FileNode> filelist = inputFileList;

            MetaChunk       = new Dictionary <long, long>();
            ChunkOffsetDict = new Dictionary <int, long>();
            string NamePKG = $"{Environment.CurrentDirectory}\\{Path.GetFileNameWithoutExtension(FileInput)}.pkg";

            Reader = new BinaryReader(File.Open(FileInput, FileMode.Open, FileAccess.Read));

            // Read header
            Reader.BaseStream.Seek(4, SeekOrigin.Begin);
            int ChunkCount = Reader.ReadInt32(); int ChunkPadding = ChunkCount.ToString().Length;

            if (!MainWindow.CNMode)
            {
                mainwindow.printlog($"{ChunkCount} subchunks detected.");
            }
            else
            {
                mainwindow.printlog($"解析到{ChunkCount}个子chunk ");
            }

            // Read file list
            DictCount = 0;
            long totalChunkSize = 0;

            for (int i = 0; i < ChunkCount; i++)
            {
                // Process file size
                byte[] ArrayTmp1      = new byte[8];
                byte[] ArrayChunkSize = Reader.ReadBytes(3);
                int    High           = ArrayChunkSize[0] >> 4;
                ArrayChunkSize[0] = BitConverter.GetBytes(High)[0];
                Array.Copy(ArrayChunkSize, ArrayTmp1, ArrayChunkSize.Length);
                long ChunkSize = BitConverter.ToInt64(ArrayTmp1, 0);
                // Fixes the original code's error on ChunkSize
                ChunkSize       = (ChunkSize >> 4) + (ChunkSize & 0xF);
                totalChunkSize += ChunkSize;

                // Process offset
                byte[] ArrayTmp2        = new byte[8];
                byte[] ArrayChunkOffset = Reader.ReadBytes(5);
                Array.Copy(ArrayChunkOffset, ArrayTmp2, ArrayChunkOffset.Length);
                long ChunkOffset = BitConverter.ToInt64(ArrayTmp2, 0);

                MetaChunk.Add(ChunkOffset, ChunkSize);
                ChunkOffsetDict.Add(i, ChunkOffset);
                DictCount = i + 1;
            }

            cur_index = 0;
            long cur_offset = ChunkOffsetDict[cur_index];
            long cur_size   = MetaChunk[cur_offset];

            ChunkDecompressed = getDecompressedChunk(cur_offset, cur_size, Reader, cur_index);
            if (cur_index + 1 < DictCount)
            {
                NextChunkDecompressed = getDecompressedChunk(ChunkOffsetDict[cur_index + 1], MetaChunk[ChunkOffsetDict[cur_index + 1]], Reader, cur_index + 1);
            }
            else
            {
                NextChunkDecompressed = new byte[0];
            }
            cur_pointer = 0x0C;
            int TotalParentCount = BitConverter.ToInt32(ChunkDecompressed, cur_pointer);

            cur_pointer += 4;
            int TotalChildrenCount = BitConverter.ToInt32(ChunkDecompressed, cur_pointer);

            cur_pointer = 0x100;
            FileNode root_node = null;

            for (int i = 0; i < TotalParentCount; i++)
            {
                string StringNameParent = getName(0x3C);
                long   FileSize         = getInt64();
                long   FileOffset       = getInt64();
                int    EntryType        = getInt32();
                int    CountChildren    = getInt32();

                if (filelist.Count == 0)
                {
                    root_node            = new FileNode(StringNameParent, false, FileInput);
                    root_node.EntireName = root_node.Name;
                    filelist.Add(root_node);
                }
                else
                {
                    root_node               = filelist[0];
                    root_node.FromChunk     = fileinput;
                    root_node.FromChunkName = $"({System.IO.Path.GetFileNameWithoutExtension(fileinput)})";
                }
                for (int j = 0; j < CountChildren; j++)
                {
                    int origin_pointer = cur_pointer;
                    int origin_loc     = cur_index;
                    if (!ChunkCache.ContainsKey(cur_index))
                    {
                        ChunkCache.Add(cur_index, ChunkDecompressed);
                    }
                    if (!ChunkCache.ContainsKey(cur_index + 1))
                    {
                        ChunkCache.Add(cur_index + 1, NextChunkDecompressed);
                    }

                    string StringNameChild = getName(0xA0);
                    FileSize   = getInt64();
                    FileOffset = getInt64();
                    EntryType  = getInt32();
                    int Unknown = getInt32();

                    if (EntryType == 0x02)
                    {
                        cur_pointer = origin_pointer;
                        if (cur_index != origin_loc)
                        {
                            cur_index             = origin_loc;
                            ChunkDecompressed     = ChunkCache[cur_index];
                            NextChunkDecompressed = ChunkCache[cur_index + 1];
                            ChunkCache.Remove(cur_index);
                            ChunkCache.Remove(cur_index + 1);
                        }
                        StringNameChild = getName(0x50);
                        getOnLength(0x68, new byte[0x68], 0);
                    }
                    string[] fathernodes = StringNameChild.Split('\\');
                    bool     isFile      = false;
                    if (EntryType == 0x02 || EntryType == 0x00)
                    {
                        isFile = true;
                    }
                    FileNode child_node = new FileNode(fathernodes[fathernodes.Length - 1], isFile, FileInput);
                    if (isFile)
                    {
                        child_node.Size         = FileSize;
                        child_node.Offset       = FileOffset;
                        child_node.ChunkIndex   = (int)(FileOffset / 0x40000);
                        child_node.ChunkPointer = (int)(FileOffset % 0x40000);
                    }
                    child_node.EntireName = StringNameChild;
                    FileNode target_node = root_node;
                    foreach (string node_name in fathernodes)
                    {
                        if (node_name.Equals(""))
                        {
                            continue;
                        }
                        foreach (FileNode node in target_node.Childern)
                        {
                            if (node.Name == node_name)
                            {
                                if (node.Name == child_node.Name)
                                {
                                    break;
                                }
                                target_node = node;
                                break;
                            }
                        }
                    }
                    bool need_add = true;
                    foreach (FileNode tmp_node in target_node.Childern)
                    {
                        if (tmp_node.Name == child_node.Name)
                        {
                            if (child_node.IsFile)
                            {
                                target_node.Childern.Remove(tmp_node);
                            }
                            else
                            {
                                tmp_node.FromChunk = child_node.FromChunk; tmp_node.FromChunkName = child_node.FromChunkName;
                                need_add           = false;
                            }
                            break;
                        }
                    }
                    if (need_add)
                    {
                        target_node.Childern.Add(child_node);
                    }
                }
                mainwindow.setProgressbar(i + 1, TotalParentCount);
            }
            ChunkCache.Clear();
            if (filelist.Count > 0)
            {
                filelist[0].getSize();
            }
            return(filelist);
        }
Пример #3
0
        private void DoExtractHandler(object sender, DoWorkEventArgs e)
        {
            extract_progress = 0;
            if (itemlist.Count > 0)
            {
                FileNode rootnode = itemlist[0];
                total_progress = rootnode.getSelectedCount();
                setProgressbarMax(total_progress);
            }
            if (total_progress == 0)
            {
                printlog("Nothing selected.");
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    ExtractBtn.IsEnabled = true;
                }));
                return;
            }
            if (!CNMode)
            {
                printlog("Export to: " + output_directory);
                printlog("It may take a long time to extract all the files you selected which depends on the file size and amount you selected.");
            }
            else
            {
                printlog("解包至: " + output_directory);
                printlog("根据你所选取的文件数量和大小,这可能会花费很长时间,请耐心等待");
            }
            int failed = 0;

            if (CombineChecked)
            {
                chunkMap.FirstOrDefault().Value.ExtractSelected(itemlist, output_directory, this);
            }
            else
            {
                failed = mainChunk.ExtractSelected(itemlist, output_directory, this);
            }
            if (failed > 0)
            {
                if (!CNMode)
                {
                    printlog($"{failed} files failed to extract in total.");
                }
                else
                {
                    printlog($"总计{failed}个文件提取失败");
                }
            }
            Dispatcher.BeginInvoke(new Action(() =>
            {
                ExtractBtn.IsEnabled = true;
            }));
            if (!CNMode)
            {
                printlog("Finished!");
            }
            else
            {
                printlog("提取完成!");
            }
        }