protected override void Save(List <Player.UndoPos> buffer, string path) { UndoCacheNode node = new UndoCacheNode(); string lastLoggedName = ""; using (FileStream fs = File.Create(path)) { BinaryWriter w = new BinaryWriter(fs); long entriesPos = 0; ChunkHeader last = default(ChunkHeader); foreach (Player.UndoPos uP in buffer) { DateTime time = Server.StartTime.AddSeconds(uP.timeDelta); int timeDiff = (int)(time - last.BaseTime).TotalSeconds; if (last.LevelName != uP.mapName || timeDiff > (65535 >> 2) || last.Entries == ushort.MaxValue) { if (!LevelInfo.ExistsOffline(uP.mapName)) { if (uP.mapName != lastLoggedName) { lastLoggedName = uP.mapName; Server.s.Log("Missing map file \"" + lastLoggedName + "\", skipping undo entries"); } continue; } Vec3U16 dims = IMapImporter.Formats[0].ReadDimensions(LevelInfo.LevelPath(uP.mapName)); node.Width = dims.X; node.Height = dims.Y; node.Length = dims.Z; WriteChunkEntries(w, last.Entries, entriesPos); node.MapName = uP.mapName; last = WriteEmptyChunk(w, node, time, ref entriesPos); } UndoCacheItem item = UndoCacheItem.Make(node, 0, uP); int flags = (item.Flags & 0xC000) | timeDiff; w.Write((ushort)flags); w.Write(item.Index); w.Write(item.Type); w.Write(item.NewType); last.Entries++; } if (last.Entries > 0) { WriteChunkEntries(w, last.Entries, entriesPos); } } }
/// <summary> Appends an item to the cache. </summary> public void Add(Level lvl, Player.UndoPos item) { lock (AddLock) { DateTime time = Server.StartTime.AddTicks(item.timeDelta * TimeSpan.TicksPerSecond); if (Tail == null) { Tail = UndoCacheNode.Make(lvl, time); Head = Tail; } if (lvl.name != Tail.MapName || lvl.Width != Tail.Width || lvl.Height != Tail.Height || lvl.Length != Tail.Length || Math.Abs((time - Tail.BaseTime).TotalSeconds) > TimeDeltaMax) { UndoCacheNode node = UndoCacheNode.Make(lvl, time); Tail.Next = node; node.Prev = Tail; Tail = node; } short timeDiff = (short)(time - Tail.BaseTime).TotalSeconds; Tail.Items.Add(UndoCacheItem.Make(Tail, timeDiff, ref item)); Count++; } }