Пример #1
0
        private static void BuildBsaPatch(string inBsaName, string outBsaName)
        {
            string outBSAFile = Path.ChangeExtension(outBsaName, ".bsa");
            string outBSAPath = Path.Combine(_dirTTWMain, outBSAFile);

            string inBSAFile = Path.ChangeExtension(inBsaName, ".bsa");
            string inBSAPath = Path.Combine(_dirFO3Data, inBSAFile);

            var renameDict = BuildRenameDict(outBsaName);

            Debug.Assert(renameDict != null);

            var patPath = Path.Combine(OutDir, Path.ChangeExtension(outBsaName, ".pat"));

            if (File.Exists(patPath))
            {
                return;
            }

            var prefix = Path.Combine(InDir, "TTW Patches", outBsaName);

            using (var inBSA = new BSA(inBSAPath))
                using (var outBSA = new BSA(outBSAPath))
                {
                    BsaDiff
                    .CreateRenameQuery(inBSA, renameDict)
                    .ToList(); // execute query

                    var oldFiles = inBSA.SelectMany(folder => folder).ToList();
                    var newFiles = outBSA.SelectMany(folder => folder).ToList();

                    var newChkDict = FileValidation.FromBSA(outBSA);

                    var joinedPatches = from patKvp in newChkDict
                                        join newBsaFile in newFiles on patKvp.Key equals newBsaFile.Filename
                                        select new
                    {
                        newBsaFile,
                        file  = patKvp.Key,
                        patch = patKvp.Value
                    };
                    var allJoinedPatches = joinedPatches.ToList();

                    var patchDict = new PatchDict(allJoinedPatches.Count);
                    foreach (var join in allJoinedPatches)
                    {
                        var oldBsaFile = oldFiles.SingleOrDefault(file => file.Filename == join.file);
                        Debug.Assert(oldBsaFile != null, "File not found: " + join.file);

                        var oldChk = FileValidation.FromBSAFile(oldBsaFile);
                        var newChk = join.patch;

                        var oldFilename = oldBsaFile.Filename;
                        if (oldFilename.StartsWith(TaleOfTwoWastelands.Properties.Resources.VoicePrefix))
                        {
                            patchDict.Add(join.file, new Patch(newChk, null));
                            continue;
                        }

                        var patches = new List <PatchInfo>();

                        var md5OldStr = Util.GetMD5String(oldBsaFile.GetContents(true));
                        var md5NewStr = Util.GetMD5String(join.newBsaFile.GetContents(true));

                        var diffPath = Path.Combine(prefix, oldFilename + "." + md5OldStr + "." + md5NewStr + ".diff");
                        var usedPath = Path.ChangeExtension(diffPath, ".used");
                        if (File.Exists(usedPath))
                        {
                            File.Move(usedPath, diffPath); //fixes moronic things
                        }
                        var altDiffs = Util.FindAlternateVersions(diffPath);
                        if (altDiffs != null)
                        {
                            foreach (var altDiff in altDiffs)
                            {
                                var altDiffBytes = GetDiff(altDiff.Item1, Diff.SIG_LZDIFF41);
                                patches.Add(new PatchInfo
                                {
                                    Metadata = new FileValidation(altDiff.Item2, 0, FileValidation.ChecksumType.Md5),
                                    Data     = altDiffBytes
                                });
                            }
                        }

                        if (newChk != oldChk)
                        {
                            byte[] diffData = GetDiff(diffPath, Diff.SIG_LZDIFF41);

                            var patchInfo = PatchInfo.FromOldDiff(diffData, oldChk);
                            Debug.Assert(patchInfo.Data != null);

                            patches.Add(patchInfo);
                        }

                        patchDict.Add(join.file, new Patch(newChk, patches.ToArray()));
                    }

                    using (var stream = File.OpenWrite(patPath))
                        patchDict.WriteAll(stream);
                }
        }
Пример #2
0
        public void Install(CancellationToken inToken)
        {
            var LinkedSource = CancellationTokenSource.CreateLinkedTokenSource(inToken);

            Token = LinkedSource.Token;

            Prompts.PromptPaths();

            _bsaDiff = DependencyRegistry.Container
                       //.With("progress").EqualTo(ProgressMinorOperation)
                       //.With("token").EqualTo(Token)
                       .GetInstance <BsaDiff>();
            _nvse = DependencyRegistry.Container
                    .With("FNVPath").EqualTo(Prompts.FalloutNVPath)
                    .GetInstance <NVSE>();

            var opProg = new InstallStatus(ProgressMajorOperation, Token)
            {
                ItemsTotal = 7 + Game.BuildableBSAs.Count + Game.CheckedESMs.Length
            };

            try
            {
                HandleStep <CheckingRequiredFilesStep>(opProg);

                if (!_nvse.Check())
                {
                    string err = null;
                    //true : should download, continue install
                    //false: should not download, continue install
                    //null : should not download, abort install
                    switch (_nvse.Prompt())
                    {
                    case true:
                        if (_nvse.Install(out err))
                        {
                            break;
                        }
                        goto default;

                    case false:
                        break;

                    default:
                        Fail(err);
                        return;
                    }
                }

                try
                {
                    const string curOp = "Creating FOMOD foundation";
                    opProg.CurrentOperation = curOp;

                    Log.File(curOp);

                    string
                        srcFolder = Path.Combine(Paths.AssetsDir, "TTW Data", "TTW Files"),
                        tarFolder = Prompts.TTWSavePath;

                    Util.CopyFolder(srcFolder, tarFolder);
                }
                finally
                {
                    //+1
                    opProg.Step();
                }

                //count BuildableBSAs
                HandleStep <BuildBsasStep>(opProg);

                try
                {
                    opProg.CurrentOperation = "Building SFX";

                    BuildSFX();
                }
                finally
                {
                    //+1
                    opProg.Step();
                }

                try
                {
                    opProg.CurrentOperation = "Building Voices";

                    BuildVoice();
                }
                finally
                {
                    //+1
                    opProg.Step();
                }

                try
                {
                    const string ttwArchive = "TaleOfTwoWastelands.bsa";
                    opProg.CurrentOperation = "Copying " + ttwArchive;

                    if (!File.Exists(Path.Combine(DirTTWMain, ttwArchive)))
                    {
                        File.Copy(Path.Combine(Paths.AssetsDir, "TTW Data", ttwArchive), Path.Combine(DirTTWMain, ttwArchive));
                    }
                }
                finally
                {
                    //+1
                    opProg.Step();
                }

                //count CheckedESMs
                if (!PatchMasters(opProg))
                {
                    return;
                }

                //+2
                {
                    const string prefix = "Copying ";
                    const string opA    = "Fallout3 music files";
                    const string opB    = "Fallout3 video files";

                    opProg.CurrentOperation = prefix + opA;
                    FalloutLineCopy(opA, Path.Combine(Paths.AssetsDir, "TTW Data", "FO3_MusicCopy.txt"));
                    opProg.Step();

                    opProg.CurrentOperation = prefix + opB;
                    FalloutLineCopy(opB, Path.Combine(Paths.AssetsDir, "TTW Data", "FO3_VideoCopy.txt"));
                    opProg.Step();
                }

                HandleStep <BuildFOMODsStep>(opProg);

                opProg.Finish();

                Log.Display("Install completed successfully.");
                MessageBox.Show(string.Format(Localization.InstalledSuccessfully, Localization.TTW));
            }
            catch (OperationCanceledException)
            {
                //intentionally cancelled - swallow exception
                Log.Dual("Install was cancelled.");
            }
            catch (Exception ex)
            {
                Log.File(ex.ToString());
                Fail("An error interrupted the install!");
                MessageBox.Show(string.Format(Localization.ErrorWhileInstalling, ex.Message), Localization.Error);
            }
        }