Sort of get /undo rewrite working, but mainly still broken.

This commit is contained in:
UnknownShadow200 2016-04-10 12:22:57 +10:00
parent 10ee303c41
commit 1993bcf13e
4 changed files with 156 additions and 129 deletions

View File

@ -23,128 +23,154 @@ using MCGalaxy.Util;
namespace MCGalaxy.Commands namespace MCGalaxy.Commands
{ {
public sealed class CmdUndo : Command public sealed class CmdUndo : Command
{ {
public override string name { get { return "undo"; } } public override string name { get { return "undo"; } }
public override string shortcut { get { return "u"; } } public override string shortcut { get { return "u"; } }
public override string type { get { return CommandTypes.Building; } } public override string type { get { return CommandTypes.Building; } }
public override bool museumUsable { get { return true; } } public override bool museumUsable { get { return true; } }
public override LevelPermission defaultRank { get { return LevelPermission.Guest; } } public override LevelPermission defaultRank { get { return LevelPermission.Guest; } }
public override CommandPerm[] AdditionalPerms { public override CommandPerm[] AdditionalPerms {
get { return new[] { get { return new[] {
new CommandPerm(LevelPermission.Operator, "The lowest rank to undo other players actions", 1), new CommandPerm(LevelPermission.Operator, "The lowest rank to undo other players actions", 1),
new CommandPerm(LevelPermission.AdvBuilder, "The lowest rank to be able to undo physics", 2), new CommandPerm(LevelPermission.AdvBuilder, "The lowest rank to be able to undo physics", 2),
}; } }; }
} }
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (p != null) p.RedoBuffer.Clear(); if (p != null) p.RedoBuffer.Clear();
int ignored = 0; int ignored = 0;
if (message == "") { if (message == "") {
if (p == null) { Player.SendMessage(null, "Console doesn't have an undo buffer."); return; } if (p == null) { Player.SendMessage(null, "Console doesn't have an undo buffer."); return; }
message = p.name.ToLower() + " 30"; UndoSelf(p); return;
} else if (p != null && int.TryParse(message, out ignored)) { } else if (p != null && int.TryParse(message, out ignored)) {
message = p.name.ToLower() + " " + message; message = p.name.ToLower() + " " + message;
} }
string[] parts = message.Split(' '); string[] parts = message.Split(' ');
bool undoPhysics = parts[0].CaselessEq("physics"); bool undoPhysics = parts[0].CaselessEq("physics");
Player who = undoPhysics ? null : PlayerInfo.Find(parts[0]); Player who = undoPhysics ? null : PlayerInfo.Find(parts[0]);
long seconds = GetSeconds(p, who, parts.Length > 1 ? parts[1] : "30"); long seconds = GetSeconds(p, who, parts.Length > 1 ? parts[1] : "30");
if (parts.Length > 1 && parts[1].CaselessEq("update")) { if (parts.Length > 1 && parts[1].CaselessEq("update")) {
UndoFile.UpgradePlayerUndoFiles(parts[0]); UndoFile.UpgradePlayerUndoFiles(parts[0]);
Player.SendMessage(p, "Updated undo files for " + parts[0] + " to the new binary format."); Player.SendMessage(p, "Updated undo files for " + parts[0] + " to the new binary format.");
return; return;
} }
if (who != null) if (who != null)
UndoOnlinePlayer(p, seconds, who); UndoOnlinePlayer(p, seconds, who);
else if (undoPhysics) else if (undoPhysics)
UndoLevelPhysics(p, seconds); UndoLevelPhysics(p, seconds);
else else
UndoOfflinePlayer(p, seconds, parts[0]); UndoOfflinePlayer(p, seconds, parts[0]);
} }
const int undoMax = -1; // allows everything to be undone. const int undoMax = -1; // allows everything to be undone.
internal static long GetSeconds(Player p, Player who, string param) { internal static long GetSeconds(Player p, Player who, string param) {
long secs; long secs;
if (param.CaselessEq("all")) { if (param.CaselessEq("all")) {
secs = (p.group.maxUndo == undoMax || p == who) ? int.MaxValue : p.group.maxUndo; secs = (p.group.maxUndo == undoMax || p == who) ? int.MaxValue : p.group.maxUndo;
} else if (!long.TryParse(param, out secs)) { } else if (!long.TryParse(param, out secs)) {
Player.SendMessage(p, "Invalid seconds, using 30 seconds."); Player.SendMessage(p, "Invalid seconds, using 30 seconds.");
return 30; return 30;
} }
if (secs == 0) secs = 5400; if (secs == 0) secs = 5400;
if (p != null && p != who && p.group.maxUndo != undoMax && secs > p.group.maxUndo) { if (p != null && p != who && p.group.maxUndo != undoMax && secs > p.group.maxUndo) {
Player.SendMessage(p, p.group.name + "s may only undo up to " + p.group.maxUndo + " seconds."); Player.SendMessage(p, p.group.name + "s may only undo up to " + p.group.maxUndo + " seconds.");
return p.group.maxUndo; return p.group.maxUndo;
} }
return secs; return secs;
} }
void UndoOnlinePlayer(Player p, long seconds, Player who) { void UndoSelf(Player p) {
if (p != null && p != who) { UndoDrawOpEntry[] entries = p.UndoDrawOps.Items;
if (who.group.Permission > p.group.Permission) { if (entries.Length == 0) {
MessageTooHighRank(p, "undo", true); return; Player.SendMessage(p, "You have no draw operations to undo.");
} Player.SendMessage(p, "Try using %T/undo <seconds> %Sinstead.");
if (!CheckAdditionalPerm(p)) { MessageNeedPerms(p, "can undo other players."); return; } return;
} }
UndoOnlineDrawOp op = new UndoOnlineDrawOp(); for (int i = entries.Length - 1; i >= 0; i--) {
op.Start = DateTime.UtcNow.AddTicks(-seconds * TimeSpan.TicksPerSecond); UndoDrawOpEntry entry = entries[i];
op.who = who; if (entry.DrawOpName == "UndoSelf") continue;
DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
Level saveLevel = op.saveLevel; UndoSelfDrawOp op = new UndoSelfDrawOp();
if (p == who) { op.who = p;
Player.SendMessage(p, "Undid your actions for the past &b" + seconds + " %Sseconds."); op.Start = entry.Start; op.End = entry.End;
} else { DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
Player.SendChatFrom(who, who.color + who.DisplayName + "%S's actions for the past &b" + seconds + " seconds were undone.", false);
}
Server.s.Log(who.name + "'s actions for the past " + seconds + " seconds were undone.");
if (saveLevel != null) saveLevel.Save(true);
}
void UndoOfflinePlayer(Player p, long seconds, string whoName) { entry.UndoDrawOpName = entry.DrawOpName;
if (!CheckAdditionalPerm(p)) { MessageNeedPerms(p, "can undo other players."); return; } entry.DrawOpName = "UndoSelf";
UndoOfflineDrawOp op = new UndoOfflineDrawOp(); return;
op.Start = DateTime.UtcNow.AddTicks(-seconds * TimeSpan.TicksPerSecond); }
op.whoName = whoName;
DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
if (op.foundUser) { Player.SendMessage(p, "Max number of draw operations that can be undone reached.");
Player.GlobalMessage(Server.FindColor(whoName) + whoName + "%S's actions for the past &b" + seconds + " %Sseconds were undone."); Player.SendMessage(p, "Try using %T/undo <seconds> %Sinstead.");
Server.s.Log(whoName + "'s actions for the past " + seconds + " seconds were undone."); }
p.level.Save(true);
} else {
Player.SendMessage(p, "Could not find player specified.");
}
}
void UndoLevelPhysics(Player p, long seconds) { void UndoOnlinePlayer(Player p, long seconds, Player who) {
if (!CheckAdditionalPerm(p, 2)) { MessageNeedPerms(p, "can undo physics.", 2); return; } if (p != null && p != who) {
if (p != null && !p.group.CanExecute("physics")) { if (who.group.Permission > p.group.Permission) {
Player.SendMessage(p, "You can only undo physics if you can use /physics."); return; MessageTooHighRank(p, "undo", true); return;
} }
Command.all.Find("physics").Use(p, "0"); if (!CheckAdditionalPerm(p)) { MessageNeedPerms(p, "can undo other players."); return; }
UndoPhysicsDrawOp op = new UndoPhysicsDrawOp(); }
op.seconds = seconds;
DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
Player.GlobalMessage("Physics were undone &b" + seconds + " %Sseconds"); UndoOnlineDrawOp op = new UndoOnlineDrawOp();
Server.s.Log( "Physics were undone &b" + seconds + " %Sseconds"); op.Start = DateTime.UtcNow.AddTicks(-seconds * TimeSpan.TicksPerSecond);
p.level.Save(true); op.who = who;
} DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
public override void Help(Player p) { Level saveLevel = op.saveLevel;
Player.SendMessage(p, "/undo [player] [seconds] - Undoes the blockchanges made by [player] in the previous [seconds]."); if (p == who) {
if (p == null || (p.group.maxUndo <= 500000 || p.group.maxUndo == 0)) Player.SendMessage(p, "Undid your actions for the past &b" + seconds + " %Sseconds.");
Player.SendMessage(p, "/undo [player] all - &cWill undo 68 years, 18 days, 15 hours, 28 minutes, 31 seconds for [player]"); } else {
if (p == null || (p.group.maxUndo <= 1800 || p.group.maxUndo == 0)) Player.SendChatFrom(who, who.color + who.DisplayName + "%S's actions for the past &b" + seconds + " seconds were undone.", false);
Player.SendMessage(p, "/undo [player] - &cWill undo 30 minutes"); }
Player.SendMessage(p, "/undo physics [seconds] - Undoes the physics for the current map"); Server.s.Log(who.name + "'s actions for the past " + seconds + " seconds were undone.");
} if (saveLevel != null) saveLevel.Save(true);
} }
void UndoOfflinePlayer(Player p, long seconds, string whoName) {
if (!CheckAdditionalPerm(p)) { MessageNeedPerms(p, "can undo other players."); return; }
UndoOfflineDrawOp op = new UndoOfflineDrawOp();
op.Start = DateTime.UtcNow.AddTicks(-seconds * TimeSpan.TicksPerSecond);
op.whoName = whoName;
DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
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);
} else {
Player.SendMessage(p, "Could not find player specified.");
}
}
void UndoLevelPhysics(Player p, long seconds) {
if (!CheckAdditionalPerm(p, 2)) { MessageNeedPerms(p, "can undo physics.", 2); return; }
if (p != null && !p.group.CanExecute("physics")) {
Player.SendMessage(p, "You can only undo physics if you can use /physics."); return;
}
Command.all.Find("physics").Use(p, "0");
UndoPhysicsDrawOp op = new UndoPhysicsDrawOp();
op.seconds = seconds;
DrawOp.DoDrawOp(op, null, p, new [] { Vec3U16.MaxVal, Vec3U16.MaxVal } );
Player.GlobalMessage("Physics were undone &b" + seconds + " %Sseconds");
Server.s.Log( "Physics were undone &b" + seconds + " %Sseconds");
p.level.Save(true);
}
public override void Help(Player p) {
Player.SendMessage(p, "/undo [player] [seconds] - Undoes the blockchanges made by [player] in the previous [seconds].");
if (p == null || (p.group.maxUndo <= 500000 || p.group.maxUndo == 0))
Player.SendMessage(p, "/undo [player] all - &cWill undo 68 years, 18 days, 15 hours, 28 minutes, 31 seconds for [player]");
if (p == null || (p.group.maxUndo <= 1800 || p.group.maxUndo == 0))
Player.SendMessage(p, "/undo [player] - &cWill undo 30 minutes");
Player.SendMessage(p, "/undo physics [seconds] - Undoes the physics for the current map");
}
}
} }

View File

@ -188,20 +188,17 @@ namespace MCGalaxy.Drawing.Ops {
entry.DrawOpName = op.Name; entry.DrawOpName = op.Name;
entry.LevelName = p.level.name; entry.LevelName = p.level.name;
entry.Start = DateTime.UtcNow; entry.Start = DateTime.UtcNow;
// Use same time method as DoBlockchange writing to undo buffer
int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
entry.Start = Server.StartTime.AddTicks(timeDelta * TimeSpan.TicksPerSecond);
bool needReveal = op.DetermineDrawOpMethod(p.level, affected); bool needReveal = op.DetermineDrawOpMethod(p.level, affected);
op.Perform(marks, p, p.level, brush); op.Perform(marks, p, p.level, brush);
entry.End = DateTime.UtcNow; timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
entry.End = Server.StartTime.AddTicks(timeDelta * TimeSpan.TicksPerSecond);
if (entry.Start > p.UndoBuffer.LastClear) { if (op.Name != "UndoSelf")
UndoDrawOpEntry[] items = p.UndoDrawOps.Items; p.UndoDrawOps.Add(entry);
if (items.Length == 25)
p.UndoDrawOps.Remove(items[0]);
} else { // UndoBuffer has been cleared during the draw op.
entry.Start = p.UndoBuffer.LastClear;
p.RemoveInvalidUndos();
}
p.UndoDrawOps.Add(entry);
DoReload(p, needReveal); DoReload(p, needReveal);
return true; return true;
} }

View File

@ -23,6 +23,10 @@ using MCGalaxy.Util;
namespace MCGalaxy.Drawing.Ops { namespace MCGalaxy.Drawing.Ops {
public class UndoSelfDrawOp : UndoOnlineDrawOp {
public override string Name { get { return "UndoSelf"; } }
}
public class UndoOnlineDrawOp : DrawOp { public class UndoOnlineDrawOp : DrawOp {
public override string Name { get { return "UndoOnline"; } } public override string Name { get { return "UndoOnline"; } }

View File

@ -151,7 +151,7 @@ namespace MCGalaxy.Util {
} }
public sealed class UndoDrawOpEntry { public sealed class UndoDrawOpEntry {
public string DrawOpName; public string DrawOpName, UndoDrawOpName;
public string LevelName; public string LevelName;
public DateTime Start, End; public DateTime Start, End;
} }