From 61183a60f6fe5ffbbec9a740006b4c95e5f527c0 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 22 Mar 2016 09:56:53 +1100 Subject: [PATCH] Move /undo handlers into own DrawOp classes, in preparation for a proper /redo rewrite. --- Commands/building/CmdUndo.cs | 121 +++++--------------------- Drawing/DrawOps/UndoDrawOp.cs | 156 ++++++++++++++++++++++++++++++++++ MCGalaxy_.csproj | 1 + 3 files changed, 177 insertions(+), 101 deletions(-) create mode 100644 Drawing/DrawOps/UndoDrawOp.cs diff --git a/Commands/building/CmdUndo.cs b/Commands/building/CmdUndo.cs index fa88edfcc..dba6aecb6 100644 --- a/Commands/building/CmdUndo.cs +++ b/Commands/building/CmdUndo.cs @@ -17,6 +17,7 @@ */ using System; using System.Collections.Generic; +using MCGalaxy.Drawing.Ops; using MCGalaxy.Util; namespace MCGalaxy.Commands @@ -57,7 +58,7 @@ namespace MCGalaxy.Commands } if (who != null) - UndoOnlinePlayer(p, seconds, parts[0], who); + UndoOnlinePlayer(p, seconds, who); else if (undoPhysics) UndoLevelPhysics(p, seconds); else @@ -82,21 +83,22 @@ namespace MCGalaxy.Commands return secs; } - void UndoOnlinePlayer(Player p, long seconds, string whoName, Player who) { - if (p != null) { - if (who.group.Permission > p.group.Permission && who != p) { + void UndoOnlinePlayer(Player p, long seconds, Player who) { + if (p != null && p != who) { + if (who.group.Permission > p.group.Permission) { Player.SendMessage(p, "Cannot undo a user of higher or equal rank"); return; } - if (who != p && (int)p.group.Permission < CommandOtherPerms.GetPerm(this, 1)) { + if ((int)p.group.Permission < CommandOtherPerms.GetPerm(this, 1)) { Player.SendMessage(p, "Only an " + Group.findPermInt(CommandOtherPerms.GetPerm(this, 1)).name + "+ may undo other people's actions"); return; } } - Level saveLevel = null; - PerformUndo(p, seconds, who.UndoBuffer, ref saveLevel); - bool foundUser = false; - UndoFile.UndoPlayer(p, whoName.ToLower(), seconds, ref foundUser); - + UndoOnlineDrawOp op = new UndoOnlineDrawOp(); + op.seconds = seconds; + op.who = who; + op.Perform(null, p, null, null); + + Level saveLevel = op.saveLevel; if (p == who) { Player.SendMessage(p, "Undid your actions for the past &b" + seconds + " %Sseconds."); } else { @@ -111,10 +113,12 @@ namespace MCGalaxy.Commands Player.SendMessage(p, "Reserved for " + Group.findPermInt(CommandOtherPerms.GetPerm(this)).name + "+"); return; } - bool foundUser = false; - UndoFile.UndoPlayer(p, whoName.ToLower(), seconds, ref foundUser); + UndoOfflineDrawOp op = new UndoOfflineDrawOp(); + op.seconds = seconds; + op.whoName = whoName; + op.Perform(null, p, null, null); - if (foundUser) { + if (op.foundUser) { Player.GlobalMessage(Server.FindColor(whoName) + whoName + "%S's actions for the past &b" + seconds + " %Sseconds were undone."); Server.s.Log(whoName + "'s actions for the past " + seconds + " seconds were undone."); p.level.Save(true); @@ -131,98 +135,13 @@ namespace MCGalaxy.Commands Player.SendMessage(p, "You can only undo physics if you can use /physics."); return; } Command.all.Find("physics").Use(p, "0"); - - if (p.level.UndoBuffer.Count != Server.physUndo) { - int count = p.level.currentUndo; - for (int i = count; i >= 0; i--) { - try { - if (!CheckBlockPhysics(p, seconds, i, p.level.UndoBuffer[i])) break; - } catch { } - } - } else { - int count = p.level.currentUndo; - for (int i = count; i >= 0; i--) { - try { - if (!CheckBlockPhysics(p, seconds, i, p.level.UndoBuffer[i])) break; - } catch { } - } - for (int i = p.level.UndoBuffer.Count - 1; i > count; i--) { - try { - if (!CheckBlockPhysics(p, seconds, i, p.level.UndoBuffer[i])) break; - } catch { } - } - } - + UndoPhysicsDrawOp drawOp = new UndoPhysicsDrawOp(); + drawOp.seconds = seconds; + drawOp.Perform(null, p, p.level, null); Player.GlobalMessage("Physics were undone &b" + seconds + " %Sseconds"); Server.s.Log( "Physics were undone &b" + seconds + " %Sseconds"); p.level.Save(true); } - - static void PerformUndo(Player p, long seconds, UndoCache cache, ref Level saveLvl) { - UndoCacheNode node = cache.Tail; - if (node == null) return; - - while (node != null) { - Level lvl = LevelInfo.FindExact(node.MapName); - if (lvl == null) { node = node.Prev; continue; } - saveLvl = lvl; - List items = node.Items; - BufferedBlockSender buffer = new BufferedBlockSender(lvl); - - 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); - DateTime time = node.BaseTime.AddTicks((item.TimeDelta + seconds) * TimeSpan.TicksPerSecond); - if (time < DateTime.UtcNow) { buffer.CheckIfSend(true); return; } - - byte b = lvl.GetTile(x, y, z); - 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); - byte extType = 0; - 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; - time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); - uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds; - if (p != null) p.RedoBuffer.Add(lvl, uP); - } - } - buffer.CheckIfSend(true); - node = node.Prev; - } - } - - bool CheckBlockPhysics(Player p, long seconds, int i, Level.UndoPos undo) { - byte b = p.level.GetTile(undo.index); - DateTime time = Server.StartTime.AddTicks((undo.flags >> 2) * TimeSpan.TicksPerSecond); - if (time.AddTicks(seconds * TimeSpan.TicksPerSecond) < DateTime.UtcNow) return false; - - byte newType = (undo.flags & 2) != 0 ? Block.custom_block : undo.newRawType; - if (b == newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { - ushort x, y, z; - p.level.IntToPos(undo.index, out x, out y, out z); - int undoIndex = p.level.currentUndo; - p.level.currentUndo = i; - p.level.currentUndo = undoIndex; - byte oldType = (undo.flags & 1) != 0 ? Block.custom_block : undo.oldRawType; - byte oldExtType = (undo.flags & 1) != 0 ? undo.oldRawType : (byte)0; - p.level.Blockchange(x, y, z, oldType, true, "", oldExtType, false); - } - return true; - } public override void Help(Player p) { Player.SendMessage(p, "/undo [player] [seconds] - Undoes the blockchanges made by [player] in the previous [seconds]."); diff --git a/Drawing/DrawOps/UndoDrawOp.cs b/Drawing/DrawOps/UndoDrawOp.cs new file mode 100644 index 000000000..126c00067 --- /dev/null +++ b/Drawing/DrawOps/UndoDrawOp.cs @@ -0,0 +1,156 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; +using MCGalaxy.Drawing.Brushes; +using MCGalaxy.Util; + +namespace MCGalaxy.Drawing.Ops { + + public class UndoOnlineDrawOp : DrawOp { + + public override string Name { get { return "UndoOnline"; } } + + internal long seconds; + internal Player who; + internal Level saveLevel = null; + + public override int GetBlocksAffected(Level lvl, Vector3U16[] marks) { return 0; } + + public override void Perform(Vector3U16[] marks, Player p, Level lvl, Brush brush) { + PerformUndo(p, ref saveLevel); + bool foundUser = false; + UndoFile.UndoPlayer(p, who.name.ToLower(), seconds, ref foundUser); + } + + void PerformUndo(Player p, ref Level saveLvl) { + UndoCache cache = who.UndoBuffer; + UndoCacheNode node = cache.Tail; + if (node == null) return; + + while (node != null) { + Level lvl = LevelInfo.FindExact(node.MapName); + if (lvl == null) { node = node.Prev; continue; } + saveLvl = lvl; + List items = node.Items; + BufferedBlockSender buffer = new BufferedBlockSender(lvl); + + 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); + DateTime time = node.BaseTime.AddTicks((item.TimeDelta + seconds) * TimeSpan.TicksPerSecond); + if (time < DateTime.UtcNow) { buffer.CheckIfSend(true); return; } + + byte b = lvl.GetTile(x, y, z); + 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); + byte extType = 0; + 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; + time = node.BaseTime.AddTicks(item.TimeDelta * TimeSpan.TicksPerSecond); + uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds; + if (p != null) p.RedoBuffer.Add(lvl, uP); + } + } + buffer.CheckIfSend(true); + node = node.Prev; + } + } + } + + public class UndoOfflineDrawOp : DrawOp { + + public override string Name { get { return "UndoOffline"; } } + + internal long seconds; + internal string whoName; + internal bool foundUser = false; + + public override int GetBlocksAffected(Level lvl, Vector3U16[] marks) { return 0; } + + public override void Perform(Vector3U16[] marks, Player p, Level lvl, Brush brush) { + UndoFile.UndoPlayer(p, whoName.ToLower(), seconds, ref foundUser); + } + } + + public class UndoPhysicsDrawOp : DrawOp { + + public override string Name { get { return "UndoPhysics"; } } + + internal long seconds; + + public override int GetBlocksAffected(Level lvl, Vector3U16[] marks) { return 0; } + + public override void Perform(Vector3U16[] marks, Player p, Level lvl, Brush brush) { + if (lvl.UndoBuffer.Count != Server.physUndo) { + int count = lvl.currentUndo; + for (int i = count; i >= 0; i--) { + try { + if (!CheckBlockPhysics(p, lvl, seconds, i)) break; + } catch { } + } + } else { + int count = p.level.currentUndo; + for (int i = count; i >= 0; i--) { + try { + if (!CheckBlockPhysics(p, lvl, seconds, i)) break; + } catch { } + } + for (int i = lvl.UndoBuffer.Count - 1; i > count; i--) { + try { + if (!CheckBlockPhysics(p, lvl, seconds, i)) break; + } catch { } + } + } + } + + bool CheckBlockPhysics(Player p, Level lvl, long seconds, int i) { + Level.UndoPos undo = lvl.UndoBuffer[i]; + byte b = lvl.GetTile(undo.index); + DateTime time = Server.StartTime.AddTicks((undo.flags >> 2) * TimeSpan.TicksPerSecond); + if (time.AddTicks(seconds * TimeSpan.TicksPerSecond) < DateTime.UtcNow) return false; + + byte newType = (undo.flags & 2) != 0 ? Block.custom_block : undo.newRawType; + if (b == newType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { + ushort x, y, z; + lvl.IntToPos(undo.index, out x, out y, out z); + int undoIndex = p.level.currentUndo; + lvl.currentUndo = i; + lvl.currentUndo = undoIndex; + byte oldType = (undo.flags & 1) != 0 ? Block.custom_block : undo.oldRawType; + byte oldExtType = (undo.flags & 1) != 0 ? undo.oldRawType : (byte)0; + lvl.Blockchange(x, y, z, oldType, true, "", oldExtType, false); + } + return true; + } + } +} diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 49a8a56d8..844a132e4 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -412,6 +412,7 @@ +