diff --git a/Commands/Moderation/CmdHighlight.cs b/Commands/Moderation/CmdHighlight.cs
index 83aff18f7..b1a326959 100644
--- a/Commands/Moderation/CmdHighlight.cs
+++ b/Commands/Moderation/CmdHighlight.cs
@@ -77,12 +77,14 @@ namespace MCGalaxy.Commands {
for (int i = items.Count - 1; i >= 0; i--) {
UndoCacheItem item = items[i];
ushort x, y, z;
- node.Unpack(item.Index, out x, out y, out z);
+ node.Unpack(item.Index, out x, out y, out z);
DateTime time = node.BaseTime.AddSeconds(item.TimeDelta + seconds);
if (time < DateTime.UtcNow) return;
byte b = lvl.GetTile(x, y, z);
- if (b == item.NewType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
+ byte newTile = 0, newExtTile = 0;
+ item.GetNewExtBlock(out newTile, out newExtTile);
+ if (b == newTile || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
if (b == Block.air || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava)
p.SendBlockchange(x, y, z, Block.red);
else
diff --git a/Commands/building/CmdRedo.cs b/Commands/building/CmdRedo.cs
index 72d46bd14..fed70566b 100644
--- a/Commands/building/CmdRedo.cs
+++ b/Commands/building/CmdRedo.cs
@@ -49,13 +49,12 @@ namespace MCGalaxy.Commands {
for (int i = items.Count - 1; i >= 0; i--) {
UndoCacheItem item = items[i];
ushort x, y, z;
- node.Unpack(item.Index, out x, out y, out z);
+ node.Unpack(item.Index, out x, out y, out z);
+ byte tile, extTile;
+ item.GetExtBlock(out tile, out extTile);
- byte type = lvl.GetTile(x, y, z), extType = 0;
- if (type == Block.custom_block)
- extType = lvl.GetExtTile(x, y, z);
- if (lvl.DoBlockchange(p, x, y, z, item.Type, item.ExtType)) {
- buffer.Add(lvl.PosToInt(x, y, z), item.Type, item.ExtType);
+ if (lvl.DoBlockchange(p, x, y, z, tile, extTile)) {
+ buffer.Add(lvl.PosToInt(x, y, z), tile, extTile);
buffer.CheckIfSend(false);
}
}
diff --git a/Commands/building/CmdUndo.cs b/Commands/building/CmdUndo.cs
index 2b7648d11..8950fd359 100644
--- a/Commands/building/CmdUndo.cs
+++ b/Commands/building/CmdUndo.cs
@@ -177,16 +177,21 @@ namespace MCGalaxy.Commands
if (time < DateTime.UtcNow) { buffer.CheckIfSend(true); return; }
byte b = lvl.GetTile(x, y, z);
- if (b == item.NewType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
+ byte newTile = 0, newExtTile = 0;
+ item.GetNewExtBlock(out newTile, out newExtTile);
+ if (b == newTile || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
Player.UndoPos uP = default(Player.UndoPos);
- uP.newtype = item.Type; uP.newExtType = item.ExtType;
byte extType = 0;
- if (b == Block.custom_block) extType = lvl.GetExtTile(x, y, z);
- if (lvl.DoBlockchange(p, x, y, z, item.Type, item.ExtType)) {
- buffer.Add(lvl.PosToInt(x, y, z), item.Type, item.ExtType);
+ if (b == Block.custom_block) extType = lvl.GetExtTile(x, y, z);
+ byte tile = 0, extTile = 0;
+ item.GetExtBlock(out tile, out extTile);
+
+ if (lvl.DoBlockchange(p, x, y, z, tile, extTile)) {
+ buffer.Add(lvl.PosToInt(x, y, z), tile, extTile);
buffer.CheckIfSend(false);
}
+ uP.newtype = tile; uP.newExtType = extTile;
uP.type = b; uP.extType = extType;
uP.x = x; uP.y = y; uP.z = z;
uP.mapName = node.MapName;
diff --git a/Player/Undo/UndoCache.cs b/Player/Undo/UndoCache.cs
index 55da35c66..d7a8cafd3 100644
--- a/Player/Undo/UndoCache.cs
+++ b/Player/Undo/UndoCache.cs
@@ -34,6 +34,8 @@ namespace MCGalaxy.Util {
/// Total number of items in the cache.
public volatile int Count;
+ public const int TimeDeltaMax = (1 << 13) - 1;
+
/// Appends an item to the cache.
public void Add(Level lvl, Player.UndoPos item) {
DateTime time = Server.StartTime.AddTicks(item.timeDelta * TimeSpan.TicksPerSecond);
@@ -43,7 +45,7 @@ namespace MCGalaxy.Util {
}
if (lvl.name != Tail.MapName || lvl.Width != Tail.Width || lvl.Height != Tail.Height ||
- lvl.Length != Tail.Length || Math.Abs((time - Tail.BaseTime).TotalSeconds) > 32767) {
+ 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;
@@ -95,16 +97,53 @@ namespace MCGalaxy.Util {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UndoCacheItem {
public int Index;
- public byte Type, ExtType;
- public byte NewType, NewExtType;
- public short TimeDelta;
+ public byte Type, NewType;
+ public ushort Flags; // upper 2 bits for 'ext' or 'physics' type, lower 14 bits for time delta.
+
+ public short TimeDelta {
+ get {
+ int delta = Flags & 0x3FFF;
+ return delta >= 0x2000 ? (short)(delta - 16384) : (short)delta;
+ }
+ }
+
+ public void GetExtBlock(out byte type, out byte extType) {
+ if ((Flags & (1 << 14)) != 0) {
+ type = Block.custom_block;
+ extType = Type;
+ } else {
+ type = Type;
+ extType = 0;
+ }
+ }
+
+ public void GetNewExtBlock(out byte type, out byte extType) {
+ if ((Flags & (1 << 15)) != 0) {
+ type = Block.custom_block;
+ extType = NewType;
+ } else {
+ type = NewType;
+ extType = 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.Type = pos.type; item.ExtType = pos.extType;
- item.NewType = pos.newtype; item.NewExtType = pos.newExtType;
- item.TimeDelta = timeDelta;
+ 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;
}
}
diff --git a/Player/Undo/UndoFileBin.cs b/Player/Undo/UndoFileBin.cs
index afead556a..f5146c706 100644
--- a/Player/Undo/UndoFileBin.cs
+++ b/Player/Undo/UndoFileBin.cs
@@ -70,13 +70,18 @@ namespace MCGalaxy.Util {
WriteChunkEntries(w, last.Entries, entriesPos);
last = WriteEmptyChunk(w, node.MapName, time, ref entriesPos);
}
+
ushort x, y, z;
node.Unpack(uP.Index, out x, out y, out z);
+ byte tile = 0, extTile = 0;
+ uP.GetExtBlock(out tile, out extTile);
+ byte newTile = 0, newExtTile = 0;
+ uP.GetNewExtBlock(out newTile, out newExtTile);
w.Write((ushort)timeDiff);
w.Write(x); w.Write(y); w.Write(z);
- w.Write(uP.Type); w.Write(uP.ExtType);
- w.Write(uP.NewType); w.Write(uP.NewExtType);
+ w.Write(tile); w.Write(extTile);
+ w.Write(newTile); w.Write(newExtTile);
last.Entries++;
}
if (last.Entries > 0)
@@ -152,7 +157,7 @@ namespace MCGalaxy.Util {
Pos.newtype = oldType; Pos.newExtType = oldExtType;
Pos.extType = newExtType; 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.Add(lvl.PosToInt(Pos.x, Pos.y, Pos.z), Pos.newtype, Pos.newExtType);
buffer.CheckIfSend(false);
}
if (p != null) p.RedoBuffer.Add(lvl, Pos);