Exemple #1
0
        public static UndoCacheItem Make(UndoCacheNode node, short timeDelta, ref Player.UndoPos pos)
        {
            UndoCacheItem item = default(UndoCacheItem);

            item.Index = pos.x + node.Width * (pos.z + node.Length * pos.y);
            item.Flags = (ushort)(timeDelta & 0x3FFF);

            if (pos.type == Block.custom_block)
            {
                item.Type   = pos.extType;
                item.Flags |= (ushort)(1 << 14);
            }
            else
            {
                item.Type = pos.type;
            }
            if (pos.newtype == Block.custom_block)
            {
                item.NewType = pos.newExtType;
                item.Flags  |= (ushort)(1 << 15);
            }
            else
            {
                item.NewType = pos.newtype;
            }
            return(item);
        }
Exemple #2
0
        protected override bool UndoEntry(Player p, string path, Vec3U16[] marks,
                                          ref byte[] temp, DateTime start)
        {
            Player.UndoPos Pos       = default(Player.UndoPos);
            int            timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;

            string[]            lines = File.ReadAllText(path).Split(' ');
            Vec3U16             min = marks[0], max = marks[1];
            bool                undoArea = min.X != ushort.MaxValue;
            BufferedBlockSender buffer   = new BufferedBlockSender(null);
            string              last     = null;

            // because we have space to end of each entry, need to subtract one otherwise we'll start at a "".
            for (int i = (lines.Length - 1) / 7; i >= 0; i--)
            {
                try {
                    // line format: mapName x y z date oldblock newblock
                    if (!InTime(lines[(i * 7) - 3], start))
                    {
                        return(false);
                    }
                    Level lvl = LevelInfo.FindExact(lines[(i * 7) - 7]);
                    if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name)))
                    {
                        continue;
                    }
                    if (!undoArea)
                    {
                        min = new Vec3U16(0, 0, 0);
                        max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1));
                    }
                    if (last == null || last != lvl.name)
                    {
                        buffer.CheckIfSend(true);
                        last = lvl.name;
                    }
                    buffer.level = lvl;
                    Pos.mapName  = lvl.name;

                    Pos.x = Convert.ToUInt16(lines[(i * 7) - 6]);
                    Pos.y = Convert.ToUInt16(lines[(i * 7) - 5]);
                    Pos.z = Convert.ToUInt16(lines[(i * 7) - 4]);
                    if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z ||
                        Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z)
                    {
                        continue;
                    }

                    Pos.newtype = Convert.ToByte(lines[(i * 7) - 1]);
                    Pos.type    = Convert.ToByte(lines[(i * 7) - 2]);
                    UndoBlock(p, lvl, Pos, timeDelta, buffer);
                } catch {
                }
            }
            buffer.CheckIfSend(true);
            return(true);
        }
Exemple #3
0
        protected internal static void UndoBlock(Player p, Level lvl, Player.UndoPos Pos,
                                                 int timeDelta, BufferedBlockSender buffer)
        {
            byte lvlTile = lvl.GetTile(Pos.x, Pos.y, Pos.z);

            if (lvlTile == Pos.newtype || Block.Convert(lvlTile) == Block.water ||
                Block.Convert(lvlTile) == Block.lava || lvlTile == Block.grass)
            {
                byte newExtType = Pos.newExtType;
                Pos.newtype   = Pos.type; Pos.newExtType = Pos.extType;
                Pos.extType   = newExtType; Pos.type = lvlTile;
                Pos.timeDelta = timeDelta;
                if (lvl.DoBlockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, Pos.newExtType))
                {
                    buffer.Add(lvl.PosToInt(Pos.x, Pos.y, Pos.z), Pos.newtype, Pos.newExtType);
                    buffer.CheckIfSend(false);
                }
            }
        }
Exemple #4
0
        /// <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++;
            }
        }
Exemple #5
0
        void PerformUndo(Player p, ref Level saveLvl)
        {
            UndoCache     cache = who.UndoBuffer;
            UndoCacheNode node  = cache.Tail;

            if (node == null)
            {
                return;
            }

            Vec3U16 min = Min, max = Max;
            bool    undoArea = min.X != ushort.MaxValue;

            Player.UndoPos Pos       = default(Player.UndoPos);
            int            timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;

            while (node != null)
            {
                Level lvl = LevelInfo.FindExact(node.MapName);
                if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name)))
                {
                    node = node.Prev; continue;
                }
                Pos.mapName = lvl.name;

                saveLvl = lvl;
                List <UndoCacheItem> items  = node.Items;
                BufferedBlockSender  buffer = new BufferedBlockSender(lvl);
                if (!undoArea)
                {
                    min = new Vec3U16(0, 0, 0);
                    max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1));
                }

                for (int i = items.Count - 1; i >= 0; i--)
                {
                    UndoCacheItem item = items[i];
                    node.Unpack(item.Index, out Pos.x, out Pos.y, out Pos.z);
                    if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z ||
                        Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z)
                    {
                        continue;
                    }

                    DateTime time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond);
                    if (time > End)
                    {
                        continue;
                    }
                    if (time < Start)
                    {
                        buffer.CheckIfSend(true); return;
                    }

                    item.GetNewBlock(out Pos.newtype, out Pos.newExtType);
                    item.GetBlock(out Pos.type, out Pos.extType);
                    UndoFile.UndoBlock(p, lvl, Pos, timeDelta, buffer);
                }
                buffer.CheckIfSend(true);
                node = node.Prev;
            }
        }
Exemple #6
0
        protected override bool UndoEntry(Player p, string path, Vec3U16[] marks,
                                          ref byte[] temp, DateTime start)
        {
            List <ChunkHeader> list = new List <ChunkHeader>();
            int timeDelta           = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;

            Player.UndoPos Pos = default(Player.UndoPos);
            Vec3U16        min = marks[0], max = marks[1];
            bool           undoArea = min.X != ushort.MaxValue;
            UndoCacheItem  item     = default(UndoCacheItem);

            using (Stream fs = File.OpenRead(path))
                using (BinaryReader r = new BinaryReader(fs))
                {
                    ReadHeaders(list, r);
                    for (int i = list.Count - 1; i >= 0; i--)
                    {
                        ChunkHeader chunk = list[i];
                        Level       lvl;
                        if (!CheckChunk(chunk, start, p, out lvl))
                        {
                            return(false);
                        }
                        if (lvl == null || (p.level != null && !p.level.name.CaselessEq(lvl.name)))
                        {
                            continue;
                        }
                        BufferedBlockSender buffer = new BufferedBlockSender(lvl);
                        if (!undoArea)
                        {
                            min = new Vec3U16(0, 0, 0);
                            max = new Vec3U16((ushort)(lvl.Width - 1), (ushort)(lvl.Height - 1), (ushort)(lvl.Length - 1));
                        }

                        Pos.mapName = chunk.LevelName;
                        fs.Seek(chunk.DataPosition, SeekOrigin.Begin);
                        if (temp == null)
                        {
                            temp = new byte[ushort.MaxValue * entrySize];
                        }
                        fs.Read(temp, 0, chunk.Entries * entrySize);

                        for (int j = chunk.Entries - 1; j >= 0; j--)
                        {
                            int offset = j * entrySize;
                            item.Flags = U16(temp, offset + 0);
                            DateTime time = chunk.BaseTime.AddTicks((item.Flags & 0x3FFF) * TimeSpan.TicksPerSecond);
                            if (time < start)
                            {
                                buffer.CheckIfSend(true); return(false);
                            }

                            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);
                            if (Pos.x < min.X || Pos.y < min.Y || Pos.z < min.Z ||
                                Pos.x > max.X || Pos.y > max.Y || Pos.z > max.Z)
                            {
                                continue;
                            }

                            item.Type    = temp[offset + 6];
                            item.NewType = temp[offset + 7];
                            item.GetBlock(out Pos.type, out Pos.extType);
                            item.GetNewBlock(out Pos.newtype, out Pos.newExtType);
                            UndoBlock(p, lvl, Pos, timeDelta, buffer);
                        }
                        buffer.CheckIfSend(true);
                    }
                }
            return(true);
        }
Exemple #7
0
 public static UndoCacheItem Make(UndoCacheNode node, short timeDelta, Player.UndoPos pos)
 {
     return(Make(node, timeDelta, ref pos));
 }