protected override IEnumerable <UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) { List <ChunkHeader> list = new List <ChunkHeader>(); UndoFormatEntry pos; UndoCacheItem item = default(UndoCacheItem); bool super = Player.IsSuper(args.Player); DateTime start = args.Start; 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; } if (!super && !args.Player.level.name.CaselessEq(chunk.LevelName)) { continue; } pos.LevelName = chunk.LevelName; s.Seek(chunk.DataPosition, SeekOrigin.Begin); if (args.Temp == null) { args.Temp = new byte[ushort.MaxValue * entrySize]; } s.Read(args.Temp, 0, chunk.Entries * entrySize); byte[] temp = args.Temp; for (int j = chunk.Entries - 1; j >= 0; j--) { int offset = j * entrySize; item.Flags = U16(temp, offset + 0); pos.Time = chunk.BaseTime.AddTicks((item.Flags & 0x3FFF) * TimeSpan.TicksPerSecond); if (pos.Time < start) { args.Stop = true; yield break; } int index = I32(temp, offset + 2); pos.X = (ushort)(index % chunk.Width); pos.Y = (ushort)((index / chunk.Width) / chunk.Length); pos.Z = (ushort)((index / chunk.Width) % chunk.Length); item.Type = temp[offset + 6]; item.NewType = temp[offset + 7]; item.GetBlock(out pos.Block, out pos.ExtBlock); item.GetNewBlock(out pos.NewBlock, out pos.NewExtBlock); yield return(pos); } } }
protected override IEnumerable <UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args) { UndoCacheNode node = cache.Tail; if (node == null) { yield break; } UndoFormatEntry pos; bool super = Player.IsSuper(args.Player); DateTime start = args.Start; while (node != null) { Level lvl = LevelInfo.FindExact(node.MapName); if (!super && !args.Player.level.name.CaselessEq(node.MapName)) { node = node.Prev; continue; } List <UndoCacheItem> items = node.Items; pos.LevelName = node.MapName; for (int i = items.Count - 1; i >= 0; i--) { UndoCacheItem item = items[i]; DateTime time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); if (time < start) { args.Stop = true; yield break; } pos.Time = time; node.Unpack(item.Index, out pos.X, out pos.Y, out pos.Z); item.GetBlock(out pos.Block, out pos.ExtBlock); item.GetNewBlock(out pos.NewBlock, out pos.NewExtBlock); yield return(pos); } node = node.Prev; } }