/// <summary> /// A cleanup rewrites the diff, it optimises the diff to be efficient for machine processing. /// </summary> /* The results of both cleanup types are often the same. The efficiency cleanup is based on the observation that a diff made up of * large numbers of small diffs edits may take longer to process (in downstream applications) or take more capacity to store or transmit than a * smaller number of larger diffs. The diff_match_patch.Diff_EditCost property sets what the cost of handling a new edit is in terms of handling * extra characters in an existing edit. The default value is 4, which means if expanding the length of a diff by three characters can eliminate * one edit, then that optimisation will reduce the total costs. */ public void CleanupEfficiency() { if (diffs == null) { return; } diffMatchPatch.diff_cleanupEfficiency(diffs); }
/// <summary> /// Creates a patch from the PatchMessage sent by the client. /// Then applies the patch to the ShadowCopy followed by applying the patch to the live server copy. /// Then creates new diffs from the live server text and the shadow (which contains the exact copy of latest client message). /// These diffs will then be send to the client so that the client now has the latest updates. /// </summary> /// <param name="message"></param> private void HandlePatchMessage(PatchMessage message) { _edits.Clear(); Edit edit = message.Edits.Pop(); Task.Factory.StartNew(() => { if (edit.ClientVersion > User.Document.ShadowCopy.ClientVersion || edit.ClientVersion == 0) { // Update Server Shadow bool success; List <Patch> patches; try { patches = _dmp.patch_make(User.Document.ShadowCopy.ShadowText, edit.Diffs); User.Document.ShadowCopy.ShadowText = _dmp.patch_apply(patches, User.Document.ShadowCopy.ShadowText)[0].ToString(); //User.Document.ShadowCopy.ClientVersion++; User.Document.BackupShadowCopy.BackupText = User.Document.ShadowCopy.ShadowText; success = true; } catch (ArgumentOutOfRangeException e) { Console.WriteLine(e); success = false; Session.BroadCastOutOfSyncResponse(Session.Document.CurrentText); } if (success) { // Update Server Current patches = _dmp.patch_make(Session.Document.CurrentText, edit.Diffs); Session.Document.CurrentText = _dmp.patch_apply(patches, Session.Document.CurrentText)[0].ToString(); Console.WriteLine( $"Updated client: {User.Username}, With test: {Session.Document.CurrentText}"); } } }).ContinueWith((result) => { List <Diff> diffs = _dmp.diff_main(User.Document.ShadowCopy.ShadowText, Session.Document.CurrentText, false); _dmp.diff_cleanupEfficiency(diffs); _edits.Push(new Edit(diffs, User.Document.ShadowCopy.ClientVersion, User.Document.ShadowCopy.ServerVersion)); SendMessage(new PatchMessage("Server", _edits)); User.Document.ShadowCopy.ShadowText = Session.Document.CurrentText; _edits.Clear(); }); }