Beispiel #1
0
        static void UndoBlock(UndoFormatArgs args, Level lvl, UndoFormatEntry P)
        {
            byte lvlBlock = lvl.GetTile(P.X, P.Y, P.Z);

            if (lvlBlock == P.NewBlock || Block.Convert(lvlBlock) == Block.water ||
                Block.Convert(lvlBlock) == Block.lava || lvlBlock == Block.grass)
            {
                if (args.Player != null)
                {
                    DrawOpBlock block;
                    block.X     = P.X; block.Y = P.Y; block.Z = P.Z;
                    block.Block = P.Block; block.ExtBlock = P.ExtBlock;
                    args.Output(block);
                }
                else
                {
                    Player.GlobalBlockchange(lvl, P.X, P.Y, P.Z, P.Block, P.ExtBlock); // TODO: rewrite this :/
                    lvl.SetTile(P.X, P.Y, P.Z, P.Block);
                    if (P.Block != Block.custom_block)
                    {
                        return;
                    }
                    lvl.SetExtTile(P.X, P.Y, P.Z, P.ExtBlock);
                }
            }
        }
Beispiel #2
0
        public static void DoUndoArea(Stream s, Vec3S32 min, Vec3S32 max,
                                      UndoFormat format, UndoFormatArgs args)
        {
            Level  lvl     = args.Player == null ? null : args.Player.level;
            string lastMap = null;

            foreach (UndoFormatEntry P in format.GetEntries(s, args))
            {
                if (P.LevelName != lastMap)
                {
                    lvl = LevelInfo.FindExact(P.LevelName);
                }
                if (lvl == null || P.Time > args.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;
                }
                UndoBlock(args, lvl, P);
            }
        }
Beispiel #3
0
        public override void EnumerateEntries(Stream s, UndoFormatArgs args)
        {
            List <ChunkHeader> list = new List <ChunkHeader>();
            UndoFormatEntry    pos;
            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) >= args.Start;
                if (!inRange)
                {
                    args.Finished = true; return;
                }
                if (!args.Map.CaselessEq(chunk.LevelName))
                {
                    continue;
                }

                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;
                    ushort flags  = U16(temp, offset + 0);
                    // upper 2 bits for 'ext' or 'physics' type, lower 14 bits for time delta.

                    // TODO: should this be instead:
                    // int delta = Flags & 0x3FFF;
                    // timeDeltaSeconds = delta >= 0x2000 ? (short)(delta - 16384) : (short)delta;
                    time = chunk.BaseTime.AddTicks((flags & 0x3FFF) * TimeSpan.TicksPerSecond);
                    if (time < args.Start)
                    {
                        args.Finished = true; return;
                    }
                    if (time > args.End)
                    {
                        continue;
                    }

                    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);

                    pos.Block    = Block.FromRaw(temp[offset + 6], (flags & (1 << 14)) != 0);
                    pos.NewBlock = Block.FromRaw(temp[offset + 7], (flags & (1 << 15)) != 0);
                    args.Output(pos);
                }
            }
        }
Beispiel #4
0
        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);
                }
            }
        }
Beispiel #5
0
        public override void EnumerateEntries(Stream s, UndoFormatArgs args)
        {
            List <ChunkHeader> list = new List <ChunkHeader>();
            UndoFormatEntry    pos;
            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) >= args.Start;
                if (!inRange)
                {
                    args.Stop = true; return;
                }
                if (!args.LevelName.CaselessEq(chunk.LevelName))
                {
                    continue;
                }

                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;
                    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);
                    pos.Z = U16(temp, offset + 6);

                    pos.Block.BlockID    = temp[offset + 8];
                    pos.Block.ExtID      = temp[offset + 9];
                    pos.NewBlock.BlockID = temp[offset + 10];
                    pos.NewBlock.ExtID   = temp[offset + 11];
                    args.Output(pos);
                }
            }
        }
Beispiel #6
0
        protected override IEnumerable <UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args)
        {
            List <ChunkHeader> list = new List <ChunkHeader>();
            UndoFormatEntry    pos;
            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 * 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;
                    pos.Time = chunk.BaseTime.AddTicks(U16(temp, offset + 0) * TimeSpan.TicksPerSecond);
                    if (pos.Time < start)
                    {
                        args.Stop = true; yield break;
                    }

                    pos.X = U16(temp, offset + 2);
                    pos.Y = U16(temp, offset + 4);
                    pos.Z = U16(temp, offset + 6);

                    pos.Block    = temp[offset + 8]; pos.ExtBlock = temp[offset + 9];
                    pos.NewBlock = temp[offset + 10]; pos.NewExtBlock = temp[offset + 11];
                    yield return(pos);
                }
            }
        }
Beispiel #7
0
        public static void DoRedo(Stream s, UndoFormat format, UndoFormatArgs args)
        {
            DrawOpBlock block;

            foreach (UndoFormatEntry P in format.GetEntries(s, args))
            {
                if (P.Time > args.End)
                {
                    continue;
                }

                block.X     = P.X; block.Y = P.Y; block.Z = P.Z;
                block.Block = P.Block; block.ExtBlock = P.ExtBlock;
                args.Output(block);
            }
        }
Beispiel #8
0
        public static void DoHighlight(Stream s, UndoFormat format, UndoFormatArgs args)
        {
            BufferedBlockSender buffer = new BufferedBlockSender(args.Player);
            Level lvl = args.Player.level;

            foreach (UndoFormatEntry P in format.GetEntries(s, args))
            {
                byte block = P.Block, newBlock = P.NewBlock;
                byte highlight = (newBlock == Block.air ||
                                  Block.Convert(block) == Block.water || block == Block.waterstill ||
                                  Block.Convert(block) == Block.lava || block == Block.lavastill)
                    ? Block.red : Block.green;

                buffer.Add(lvl.PosToInt(P.X, P.Y, P.Z), highlight, 0);
            }
            buffer.Send(true);
        }
Beispiel #9
0
        static void UpgradeFiles(string dir, string name)
        {
            string path = Path.Combine(dir, name);

            if (!Directory.Exists(path))
            {
                return;
            }
            string[] files = Directory.GetFiles(path);
            List <Player.UndoPos> buffer = new List <Player.UndoPos>();
            UndoFormatArgs        args   = new UndoFormatArgs(null, DateTime.MinValue, DateTime.MaxValue, null);

            for (int i = 0; i < files.Length; i++)
            {
                path = files[i];
                if (!path.EndsWith(BinFormat.Ext) && !path.EndsWith(TxtFormat.Ext))
                {
                    continue;
                }
                IEnumerable <UndoFormatEntry> data = null;
                Player.UndoPos pos;

                using (FileStream s = File.OpenRead(path)) {
                    data = path.EndsWith(BinFormat.Ext)
                        ? BinFormat.GetEntries(s, args) : TxtFormat.GetEntries(s, args);

                    foreach (UndoFormatEntry P in data)
                    {
                        pos.x       = P.X; pos.y = P.Y; pos.z = P.Z;
                        pos.type    = P.Block; pos.extType = P.ExtBlock;
                        pos.newtype = P.NewBlock; pos.newExtType = P.NewExtBlock;

                        pos.timeDelta = (int)P.Time.Subtract(Server.StartTimeLocal).TotalSeconds;
                        pos.mapName   = P.LevelName;
                        buffer.Add(pos);
                    }

                    buffer.Reverse();
                    string newPath = Path.ChangeExtension(path, NewFormat.Ext);
                    NewFormat.Save(buffer, newPath);
                }
                File.Delete(path);
            }
        }
Beispiel #10
0
        public static void DoUndo(Stream s, UndoFormat format, UndoFormatArgs args)
        {
            Level  lvl     = args.Player == null ? null : args.Player.level;
            string lastMap = null;

            foreach (UndoFormatEntry P in format.GetEntries(s, args))
            {
                if (P.LevelName != lastMap)
                {
                    lvl = LevelInfo.FindExact(P.LevelName);
                }
                if (lvl == null || P.Time > args.End)
                {
                    continue;
                }

                UndoBlock(args, lvl, P);
            }
        }
Beispiel #11
0
        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;
            }
        }
Beispiel #12
0
        public static void DoUndo(string target, ref bool found, UndoFormatArgs args)
        {
            List <string> files = GetUndoFiles(target);

            if (files.Count == 0)
            {
                return;
            }
            found = true;

            foreach (string file in files)
            {
                using (Stream s = File.OpenRead(file)) {
                    DoUndo(s, GetFormat(file), args);
                    if (args.Stop)
                    {
                        break;
                    }
                }
            }
        }
Beispiel #13
0
        public override void EnumerateEntries(Stream s, UndoFormatArgs args)
        {
            UndoFormatEntry pos = default(UndoFormatEntry);

            string[] lines = new StreamReader(s).ReadToEnd().SplitSpaces();
            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('&', ' ');
                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;
                }

                pos.X = ushort.Parse(lines[(i * items) - 6]);
                pos.Y = ushort.Parse(lines[(i * items) - 5]);
                pos.Z = ushort.Parse(lines[(i * items) - 4]);

                pos.Block.BlockID    = byte.Parse(lines[(i * items) - 2]);
                pos.NewBlock.BlockID = byte.Parse(lines[(i * items) - 1]);
                args.Output(pos);
            }
        }
Beispiel #14
0
        protected override IEnumerable <UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args)
        {
            UndoFormatEntry pos;

            pos.NewExtBlock = 0; pos.ExtBlock = 0;
            string[] lines = new StreamReader(s).ReadToEnd().Split(' ');
            Player   p     = args.Player;
            bool     super = p == null || p.ircNick != null;
            DateTime start = args.Start;

            // 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;
                }

                string map = lines[(i * items) - 7];
                if (!super && !p.level.name.CaselessEq(map))
                {
                    continue;
                }
                pos.LevelName = map;

                pos.X = ushort.Parse(lines[(i * items) - 6]);
                pos.Y = ushort.Parse(lines[(i * items) - 5]);
                pos.Z = ushort.Parse(lines[(i * items) - 4]);

                pos.Block    = byte.Parse(lines[(i * items) - 2]);
                pos.NewBlock = byte.Parse(lines[(i * items) - 1]);
                yield return(pos);
            }
        }
Beispiel #15
0
 /// <summary> Enumerates through all the entries in the undo file. </summary>
 public abstract void EnumerateEntries(Stream s, UndoFormatArgs args);
Beispiel #16
0
 protected abstract IEnumerable <UndoFormatEntry> GetEntries(Stream s, UndoFormatArgs args);