diff --git a/MCGalaxy/Database/Undo/UndoFormat.cs b/MCGalaxy/Database/Undo/UndoFormat.cs index 566b7abe4..97eb97f31 100644 --- a/MCGalaxy/Database/Undo/UndoFormat.cs +++ b/MCGalaxy/Database/Undo/UndoFormat.cs @@ -38,7 +38,7 @@ namespace MCGalaxy.Undo { public static UndoFormat NewFormat = new UndoFormatCBin(); /// Enumerates through all the entries in the undo file. - public abstract IEnumerable GetEntries(Stream s, UndoFormatArgs args); + public abstract void EnumerateEntries(Stream s, UndoFormatArgs args); /// File extension of undo files in this format. protected abstract string Ext { get; } @@ -113,15 +113,21 @@ namespace MCGalaxy.Undo { public bool Stop; /// First instance in time that undo data should be retrieved back to. - internal readonly DateTime Start; + internal readonly DateTime Start; - public UndoFormatArgs(string lvlName, DateTime start) { - LevelName = lvlName; Start = start; + /// Last instance in time that undo data should be retrieved up to. + internal readonly DateTime End; + + /// Performs action on the given undo format entry. + public Action Output; + + public UndoFormatArgs(string lvlName, DateTime start, DateTime end, + Action output) { + LevelName = lvlName; Start = start; End = end; Output = output; } } public struct UndoFormatEntry { - public DateTime Time; public ushort X, Y, Z; public ExtBlock Block; public ExtBlock NewBlock; diff --git a/MCGalaxy/Database/Undo/UndoFormatBin.cs b/MCGalaxy/Database/Undo/UndoFormatBin.cs index e2571e793..509562e88 100644 --- a/MCGalaxy/Database/Undo/UndoFormatBin.cs +++ b/MCGalaxy/Database/Undo/UndoFormatBin.cs @@ -28,17 +28,17 @@ namespace MCGalaxy.Undo { protected override string Ext { get { return ".unbin"; } } const int entrySize = 12; - public override IEnumerable GetEntries(Stream s, UndoFormatArgs args) { + public override void EnumerateEntries(Stream s, UndoFormatArgs args) { List list = new List(); UndoFormatEntry pos; - DateTime start = args.Start; + DateTime time; ReadHeaders(list, s); for (int i = list.Count - 1; i >= 0; i--) { ChunkHeader chunk = list[i]; // Can we safely discard the entire chunk? - bool inRange = chunk.BaseTime.AddTicks(65536 * TimeSpan.TicksPerSecond) >= start; - if (!inRange) { args.Stop = true; yield break; } + bool inRange = chunk.BaseTime.AddTicks(65536 * TimeSpan.TicksPerSecond) >= args.Start; + if (!inRange) { args.Stop = true; return; } if (!args.LevelName.CaselessEq(chunk.LevelName)) continue; s.Seek(chunk.DataPosition, SeekOrigin.Begin); @@ -49,8 +49,9 @@ namespace MCGalaxy.Undo { for (int j = chunk.Entries - 1; j >= 0; j-- ) { int offset = j * entrySize; - pos.Time = chunk.BaseTime.AddTicks(U16(temp, offset + 0) * TimeSpan.TicksPerSecond); - if (pos.Time < start) { args.Stop = true; yield break; } + time = chunk.BaseTime.AddTicks(U16(temp, offset + 0) * TimeSpan.TicksPerSecond); + if (time < args.Start) { args.Stop = true; return; } + if (time > args.End) continue; pos.X = U16(temp, offset + 2); pos.Y = U16(temp, offset + 4); @@ -60,11 +61,12 @@ namespace MCGalaxy.Undo { pos.Block.ExtID = temp[offset + 9]; pos.NewBlock.BlockID = temp[offset + 10]; pos.NewBlock.ExtID = temp[offset + 11]; - yield return pos; + args.Output(pos); } } } + static ushort U16(byte[] buffer, int offset) { return (ushort)(buffer[offset + 0] | buffer[offset + 1] << 8); } diff --git a/MCGalaxy/Database/Undo/UndoFormatCBin.cs b/MCGalaxy/Database/Undo/UndoFormatCBin.cs index 8f9ed09a8..9f05842e2 100644 --- a/MCGalaxy/Database/Undo/UndoFormatCBin.cs +++ b/MCGalaxy/Database/Undo/UndoFormatCBin.cs @@ -28,17 +28,17 @@ namespace MCGalaxy.Undo { protected override string Ext { get { return ".uncbin"; } } const int entrySize = 8; - public override IEnumerable GetEntries(Stream s, UndoFormatArgs args) { + public override void EnumerateEntries(Stream s, UndoFormatArgs args) { List list = new List(); UndoFormatEntry pos; - DateTime start = args.Start; + DateTime time; ReadHeaders(list, s); for (int i = list.Count - 1; i >= 0; i--) { ChunkHeader chunk = list[i]; // Can we safely discard the entire chunk? - bool inRange = chunk.BaseTime.AddTicks((65536 >> 2) * TimeSpan.TicksPerSecond) >= start; - if (!inRange) { args.Stop = true; yield break; } + bool inRange = chunk.BaseTime.AddTicks((65536 >> 2) * TimeSpan.TicksPerSecond) >= args.Start; + if (!inRange) { args.Stop = true; return; } if (!args.LevelName.CaselessEq(chunk.LevelName)) continue; s.Seek(chunk.DataPosition, SeekOrigin.Begin); @@ -55,8 +55,9 @@ namespace MCGalaxy.Undo { // TODO: should this be instead: // int delta = Flags & 0x3FFF; // timeDeltaSeconds = delta >= 0x2000 ? (short)(delta - 16384) : (short)delta; - pos.Time = chunk.BaseTime.AddTicks((flags & 0x3FFF) * TimeSpan.TicksPerSecond); - if (pos.Time < start) { args.Stop = true; yield break; } + time = chunk.BaseTime.AddTicks((flags & 0x3FFF) * TimeSpan.TicksPerSecond); + if (time < args.Start) { args.Stop = true; return; } + if (time > args.End) continue; int index = I32(temp, offset + 2); pos.X = (ushort)(index % chunk.Width); @@ -65,11 +66,12 @@ namespace MCGalaxy.Undo { pos.Block = ExtBlock.FromRaw(temp[offset + 6], (flags & (1 << 14)) != 0); pos.NewBlock = ExtBlock.FromRaw(temp[offset + 7], (flags & (1 << 15)) != 0); - yield return pos; + args.Output(pos); } } } + static ushort U16(byte[] buffer, int offset) { return (ushort)(buffer[offset + 0] | buffer[offset + 1] << 8); } diff --git a/MCGalaxy/Database/Undo/UndoFormatText.cs b/MCGalaxy/Database/Undo/UndoFormatText.cs index c08a964d0..8dd23e8ea 100644 --- a/MCGalaxy/Database/Undo/UndoFormatText.cs +++ b/MCGalaxy/Database/Undo/UndoFormatText.cs @@ -27,18 +27,19 @@ namespace MCGalaxy.Undo { protected override string Ext { get { return ".undo"; } } - public override IEnumerable GetEntries(Stream s, UndoFormatArgs args) { + public override void EnumerateEntries(Stream s, UndoFormatArgs args) { UndoFormatEntry pos = default(UndoFormatEntry); string[] lines = new StreamReader(s).ReadToEnd().SplitSpaces(); - DateTime start = args.Start; + DateTime time; // because we have space to end of each entry, need to subtract one otherwise we'll start at a "". const int items = 7; for (int i = (lines.Length - 1) / items; i > 0; i--) { // line format: mapName x y z date oldblock newblock string timeRaw = lines[(i * items) - 3].Replace('&', ' '); - pos.Time = DateTime.Parse(timeRaw, CultureInfo.InvariantCulture); - if (pos.Time < start) { args.Stop = true; yield break; } + time = DateTime.Parse(timeRaw, CultureInfo.InvariantCulture); + if (time < args.Start) { args.Stop = true; return; } + if (time > args.End) continue; string map = lines[(i * items) - 7]; if (!args.LevelName.CaselessEq(map)) continue; @@ -49,7 +50,7 @@ namespace MCGalaxy.Undo { pos.Block.BlockID = byte.Parse(lines[(i * items) - 2]); pos.NewBlock.BlockID = byte.Parse(lines[(i * items) - 1]); - yield return pos; + args.Output(pos); } } } diff --git a/MCGalaxy/Drawing/DrawOps/HighlightDrawOp.cs b/MCGalaxy/Drawing/DrawOps/HighlightDrawOp.cs index 1374af268..33d038fb8 100644 --- a/MCGalaxy/Drawing/DrawOps/HighlightDrawOp.cs +++ b/MCGalaxy/Drawing/DrawOps/HighlightDrawOp.cs @@ -67,8 +67,8 @@ namespace MCGalaxy.Drawing.Ops { } } - UndoFormatArgs args = new UndoFormatArgs(Level.name, Start); - DoOldHighlight(args); + UndoFormatArgs args = new UndoFormatArgs(Level.name, Start, DateTime.MaxValue, OldHighlightBlock); + PerformOldHighlight(args); } Action output; @@ -80,8 +80,8 @@ namespace MCGalaxy.Drawing.Ops { ExtBlock newBlock = ExtBlock.FromRaw(e.NewRaw, (e.Flags & BlockDBFlags.NewCustom) != 0); ExtBlock highlight = (newBlock.BlockID == Block.air - || Block.Convert(oldBlock.BlockID) == Block.water || oldBlock.BlockID == Block.waterstill - || Block.Convert(oldBlock.BlockID) == Block.lava || oldBlock.BlockID == Block.lavastill) + || Block.Convert(oldBlock.BlockID) == Block.water || oldBlock.BlockID == Block.waterstill + || Block.Convert(oldBlock.BlockID) == Block.lava || oldBlock.BlockID == Block.lavastill) ? DeleteHighlight : PlaceHighlight; int x = e.Index % dims.X; @@ -95,35 +95,32 @@ namespace MCGalaxy.Drawing.Ops { } - void DoOldHighlight(UndoFormatArgs args) { - List files = UndoFormat.GetUndoFiles(who.ToLower()); + void PerformOldHighlight(UndoFormatArgs args) { + List files = UndoFormat.GetUndoFiles(who.ToLower()); if (files.Count == 0) return; found = true; foreach (string file in files) { using (Stream s = File.OpenRead(file)) { - DoOldHighlight(s, UndoFormat.GetFormat(file), args); + UndoFormat.GetFormat(file).EnumerateEntries(s, args); if (args.Stop) break; } } } - void DoOldHighlight(Stream s, UndoFormat format, UndoFormatArgs args) { - DrawOpBlock block; + void OldHighlightBlock(UndoFormatEntry P) { + ExtBlock old = P.Block, newBlock = P.NewBlock; + if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) return; + if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) return; - foreach (UndoFormatEntry P in format.GetEntries(s, args)) { - ExtBlock old = P.Block, newBlock = P.NewBlock; - if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) continue; - if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) continue; - - block.Block = (newBlock.BlockID == Block.air - || Block.Convert(old.BlockID) == Block.water || old.BlockID == Block.waterstill - || Block.Convert(old.BlockID) == Block.lava || old.BlockID == Block.lavastill) - ? DeleteHighlight : PlaceHighlight; - - block.X = P.X; block.Y = P.Y; block.Z = P.Z; - output(block); - } + DrawOpBlock block; + block.Block = (newBlock.BlockID == Block.air + || Block.Convert(old.BlockID) == Block.water || old.BlockID == Block.waterstill + || Block.Convert(old.BlockID) == Block.lava || old.BlockID == Block.lavastill) + ? DeleteHighlight : PlaceHighlight; + + block.X = P.X; block.Y = P.Y; block.Z = P.Z; + output(block); } } } diff --git a/MCGalaxy/Drawing/DrawOps/UndoDrawOp.cs b/MCGalaxy/Drawing/DrawOps/UndoDrawOp.cs index 2b658be37..fb56cbd95 100644 --- a/MCGalaxy/Drawing/DrawOps/UndoDrawOp.cs +++ b/MCGalaxy/Drawing/DrawOps/UndoDrawOp.cs @@ -71,8 +71,8 @@ namespace MCGalaxy.Drawing.Ops { } } - UndoFormatArgs args = new UndoFormatArgs(Level.name, Start); - DoOldUndo(args); + UndoFormatArgs args = new UndoFormatArgs(Level.name, Start, End, OldUndoBlock); + PerformOldUndo(args); } Action output; @@ -93,34 +93,31 @@ namespace MCGalaxy.Drawing.Ops { } - void DoOldUndo(UndoFormatArgs args) { + void PerformOldUndo(UndoFormatArgs args) { List files = UndoFormat.GetUndoFiles(who.ToLower()); if (files.Count == 0) return; found = true; foreach (string file in files) { using (Stream s = File.OpenRead(file)) { - DoOldUndo(s, UndoFormat.GetFormat(file), args); + UndoFormat.GetFormat(file).EnumerateEntries(s, args); if (args.Stop) break; } } } - void DoOldUndo(Stream s, UndoFormat format, UndoFormatArgs args) { - DrawOpBlock block; - foreach (UndoFormatEntry P in format.GetEntries(s, args)) { - if (P.Time > End) continue; - if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) continue; - if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) continue; + void OldUndoBlock(UndoFormatEntry P) { + if (P.X < Min.X || P.Y < Min.Y || P.Z < Min.Z) return; + if (P.X > Max.X || P.Y > Max.Y || P.Z > Max.Z) return; + + byte lvlBlock = Level.GetTile(P.X, P.Y, P.Z); + if (lvlBlock == P.NewBlock.BlockID || Block.Convert(lvlBlock) == Block.water + || Block.Convert(lvlBlock) == Block.lava || lvlBlock == Block.grass) { - byte lvlBlock = Level.GetTile(P.X, P.Y, P.Z); - if (lvlBlock == P.NewBlock.BlockID || Block.Convert(lvlBlock) == Block.water - || Block.Convert(lvlBlock) == Block.lava || lvlBlock == Block.grass) { - - block.X = P.X; block.Y = P.Y; block.Z = P.Z; - block.Block = P.Block; - output(block); - } + DrawOpBlock block; + block.X = P.X; block.Y = P.Y; block.Z = P.Z; + block.Block = P.Block; + output(block); } } }