/// <summary> /// Patches the file segments in a stream. /// </summary> /// <param name="changes">The changes to make to the segments and their data.</param> /// <param name="stream">The stream to write changes to.</param> public static void PatchSegments(IEnumerable <SegmentChange> changes, IStream stream) { // Sort changes by their offsets var changesByOffset = new SortedList <uint, SegmentChange>(); foreach (SegmentChange change in changes) { changesByOffset[change.OldOffset] = change; } // Now adjust each segment foreach (SegmentChange change in changesByOffset.Values) { // Resize it if necessary if (change.NewSize != change.OldSize) { if (change.ResizeAtEnd) { stream.SeekTo(change.NewOffset + change.OldSize); } else { stream.SeekTo(change.NewOffset); } StreamUtil.Insert(stream, change.NewSize - change.OldSize, 0); } // Patch its data DataPatcher.PatchData(change.DataChanges, change.NewOffset, stream); } }
/// <summary> /// Applies a patch to a cache file. /// </summary> /// <param name="patch">The patch to apply.</param> /// <param name="cacheFile">The cache file to apply the patch to. After the patch is applied, it may have to be reloaded.</param> /// <param name="stream">The stream to write changes to.</param> public static void ApplyPatch(Patch patch, ICacheFile cacheFile, IStream stream) { if (patch.MapInternalName != cacheFile.InternalName) { throw new ArgumentException("The patch is for a different cache file. Expected \"" + patch.MapInternalName + "\" but got \"" + cacheFile.InternalName + "\"."); } SegmentPatcher.PatchSegments(patch.SegmentChanges, stream); #region Deprecated DataPatcher.PatchData(patch.MetaChanges, (uint)-cacheFile.MetaArea.PointerMask, stream); if (patch.LanguageChanges.Count > 0) { LocalePatcher.WriteLanguageChanges(patch.LanguageChanges, cacheFile, stream); cacheFile.SaveChanges(stream); } #endregion }