diff --git a/MCGalaxy/Commands/Moderation/CmdUndoPlayer.cs b/MCGalaxy/Commands/Moderation/CmdUndoPlayer.cs index 7288ecf8c..cfd961c32 100644 --- a/MCGalaxy/Commands/Moderation/CmdUndoPlayer.cs +++ b/MCGalaxy/Commands/Moderation/CmdUndoPlayer.cs @@ -30,7 +30,7 @@ namespace MCGalaxy.Commands.Moderation { public override bool museumUsable { get { return true; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } public override CommandAlias[] Aliases { - get { return new[] { new CommandAlias("xundo", null, "all"), + get { return new[] { new CommandAlias("xundo", null, "all"), new CommandAlias("undoarea", "area"), new CommandAlias("ua", "area") }; } } @@ -72,7 +72,21 @@ namespace MCGalaxy.Commands.Moderation { UndoDrawOp op = new UndoDrawOp(); op.Start = DateTime.UtcNow.Subtract(delta); op.who = names[0]; op.ids = ids; - DrawOpPerformer.Do(op, null, p, marks); + + if (Player.IsSuper(p)) { + // undo them across all loaded levels + Level[] levels = LevelInfo.Loaded.Items; + if (p == null) p = new ConsolePlayer(); + + foreach (Level lvl in levels) { + op.SetMarks(marks); + op.SetLevel(lvl); + op.Player = p; p.level = lvl; + DrawOpPerformer.DoQueuedDrawOp(p, op, null, marks); + } + } else { + DrawOpPerformer.Do(op, null, p, marks); + } string namesStr = names.Join(name => PlayerInfo.GetColoredName(p, name)); if (op.found) { @@ -83,6 +97,19 @@ namespace MCGalaxy.Commands.Moderation { } } + // TODO: nasty hack, need to find a better way of doing this + sealed class ConsolePlayer : Player { + public ConsolePlayer() : base("(console)") { + group = Group.NobodyRank; + UserID = NameConverter.InvalidNameID("(console)"); + } + + public override void SendMessage(byte id, string message, bool colorParse = true) { + message = Chat.Format(message, this, colorParse); + Server.s.Log(message); + } + } + int[] GetIds(Player p, string[] parts, out string[] names) { int count = Math.Max(1, parts.Length - 1); List ids = new List(); diff --git a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs index ab8347a27..1f37cc0a9 100644 --- a/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs +++ b/MCGalaxy/Drawing/DrawOps/DrawOpPerformer.cs @@ -79,23 +79,14 @@ namespace MCGalaxy.Drawing.Ops { Player.Message(p, format, op.Name, affected); } - AppendDrawOp(p, op, brush, marks, affected); + DoQueuedDrawOp(p, op, brush, marks); return true; } - static void AppendDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks, long affected) { - if (p == null) { - BufferedBlockSender buffer = new BufferedBlockSender(op.Level); - op.Perform(marks, brush, b => ConsoleOutputBlock(b, op.Level, buffer)); - buffer.Send(true); - return; - } - + internal static void DoQueuedDrawOp(Player p, DrawOp op, Brush brush, Vec3S32[] marks) { PendingDrawOp item = new PendingDrawOp(); - item.Op = op; - item.Brush = brush; - item.Marks = marks; - + item.Op = op; item.Brush = brush; item.Marks = marks; + lock (p.pendingDrawOpsLock) { p.PendingDrawOps.Add(item); // Another thread is already processing draw ops. @@ -104,12 +95,6 @@ namespace MCGalaxy.Drawing.Ops { ProcessDrawOps(p); } - static void ConsoleOutputBlock(DrawOpBlock b, Level lvl, BufferedBlockSender buffer) { - int index = lvl.PosToInt(b.X, b.Y, b.Z); - if (!lvl.DoPhysicsBlockchange(index, b.Block, false, default(PhysicsArgs))) return; - buffer.Add(index, b.Block.BlockID, b.Block.ExtID); - } - static void ProcessDrawOps(Player p) { while (true) { PendingDrawOp item; @@ -144,7 +129,7 @@ namespace MCGalaxy.Drawing.Ops { if (item.Op.TotalModified > Server.DrawReloadLimit) DoReload(p, item.Op.Level); - item.Op.TotalModified = 0; // reset total modified (as drawop instances are used in static mode) + item.Op.TotalModified = 0; // reset total modified (as drawop instances are reused in static mode) } } diff --git a/MCGalaxy/Events/Player.Events.cs b/MCGalaxy/Events/Player.Events.cs index a04c48938..93a6f54c9 100644 --- a/MCGalaxy/Events/Player.Events.cs +++ b/MCGalaxy/Events/Player.Events.cs @@ -22,7 +22,7 @@ namespace MCGalaxy { public enum PlayerAction { Joker, Unjoker, AFK, UnAFK, JoinWorld, Me, Review }; /// This is the player object - public sealed partial class Player { + public partial class Player { public bool cancelcommand, cancelchat, cancelmove, cancelBlock, cancelmysql; public bool cancelmessage, cancellogin, cancelconnecting; diff --git a/MCGalaxy/Network/IRCPlugin/IRCHandlers.cs b/MCGalaxy/Network/IRCPlugin/IRCHandlers.cs index 76d8d7d72..baf122730 100644 --- a/MCGalaxy/Network/IRCPlugin/IRCHandlers.cs +++ b/MCGalaxy/Network/IRCPlugin/IRCHandlers.cs @@ -236,7 +236,7 @@ namespace MCGalaxy.Network { if (!whoCmd || (DateTime.UtcNow - last).TotalSeconds <= 5) return false; try { - Player p = MakeIRCPlayer(user.Nick, channel); + Player p = new IRCPlayer(user.Nick, channel, bot); p.group = Group.GuestRank; Command.all.Find("players").Use(p, ""); } catch (Exception e) { @@ -250,7 +250,7 @@ namespace MCGalaxy.Network { bool HandleIRCCommand(UserInfo user, string channel, string cmdName, string cmdArgs) { Command cmd = Command.all.Find(cmdName); - Player p = MakeIRCPlayer(user.Nick, channel); + Player p = new IRCPlayer(user.Nick, channel, bot); if (cmd == null) { Player.Message(p, "Unknown command!"); return false; } string logCmd = cmdArgs == "" ? cmdName : cmdName + " " + cmdArgs; @@ -280,26 +280,40 @@ namespace MCGalaxy.Network { if (!foundAtAll) { error = "You are not on the bot's list of users for some reason, please leave and rejoin."; return false; - } + } if (bot.BannedCommands.Contains(cmdName)) { error = "You are not allowed to use this command from IRC."; } return false; } + - - static Player MakeIRCPlayer(string ircNick, string ircChannel) { - Player p = new Player("IRC"); - p.group = Group.findPerm(Server.ircControllerRank); - if (p.group == null) p.group = Group.NobodyRank; + sealed class IRCPlayer : Player { + public readonly string IRCChannel, IRCNick; + public readonly IRCBot Bot; - p.ircChannel = ircChannel; - p.ircNick = ircNick; - p.color = "&a"; + public IRCPlayer(string ircChannel, string ircNick, IRCBot bot) : base("IRC") { + group = Group.findPerm(Server.ircControllerRank); + if (group == null) group = Group.NobodyRank; + + IRCChannel = ircChannel; + IRCNick = ircNick; + color = "&a"; + Bot = bot; + + if (ircNick != null) + UserID = NameConverter.InvalidNameID("(IRC " + ircNick + ")"); + } - if (ircNick != null) - p.UserID = NameConverter.InvalidNameID("(IRC " + ircNick + ")"); - return p; + public override void SendMessage(byte id, string message, bool colorParse = true) { + message = Chat.Format(message, this, colorParse); + + if (IRCChannel != null) { + Bot.Message(IRCChannel, message); + } else { + Bot.Pm(IRCNick, message); + } + } } void Listener_OnRegistered() { @@ -454,7 +468,7 @@ namespace MCGalaxy.Network { if (verify == IRCControllerVerify.None) return true; if (verify == IRCControllerVerify.HalfOp) { - string prefix = GetPrefix(chanNicks[index]); + string prefix = GetPrefix(chanNicks[index]); if (prefix == "" || prefix == "+") { error = "You must be at least a half-op on the channel to use commands from IRC."; return false; } diff --git a/MCGalaxy/Network/Player.Networking.cs b/MCGalaxy/Network/Player.Networking.cs index ab8521a31..6a8010837 100644 --- a/MCGalaxy/Network/Player.Networking.cs +++ b/MCGalaxy/Network/Player.Networking.cs @@ -21,7 +21,7 @@ using MCGalaxy.Events; using MCGalaxy.Network; namespace MCGalaxy { - public sealed partial class Player : IDisposable { + public partial class Player : IDisposable { public bool hasCpe, finishedCpeLogin = false; public string appName; @@ -103,11 +103,7 @@ namespace MCGalaxy { storedHelp += message + "\r\n"; else Server.s.Log(message); - } else if (p.ircChannel != null) { - Server.IRC.Message(p.ircChannel, message); - } else if (p.ircNick != null) { - Server.IRC.Pm(p.ircNick, message); - } else { + } else { p.SendMessage(0, Server.DefaultColor + message, colorParse); } } @@ -120,7 +116,7 @@ namespace MCGalaxy { SendMessage(0, Server.DefaultColor + message, colorParse); } - public void SendMessage(byte id, string message, bool colorParse = true) { + public virtual void SendMessage(byte id, string message, bool colorParse = true) { message = Chat.Format(message, this, colorParse); int totalTries = 0; diff --git a/MCGalaxy/Player/Player.Fields.cs b/MCGalaxy/Player/Player.Fields.cs index 439fd0f54..af1b21714 100644 --- a/MCGalaxy/Player/Player.Fields.cs +++ b/MCGalaxy/Player/Player.Fields.cs @@ -28,7 +28,7 @@ namespace MCGalaxy { public enum VoteKickChoice { NotYetVoted, Yes, No } - public sealed partial class Player : IDisposable { + public partial class Player : IDisposable { public Dictionary ExtraData = new Dictionary(); @@ -103,7 +103,7 @@ namespace MCGalaxy { public DateTime NextReviewTime, NextEat; public float ReachDistance = 5; public bool hackrank; - internal string ircChannel, ircNick; + public bool SuperUser; public string FullName { get { return color + prefix + DisplayName; } } @@ -263,6 +263,6 @@ namespace MCGalaxy { public bool verifiedName; /// Returns whether the given player is console or IRC. - public static bool IsSuper(Player p) { return p == null || p.ircChannel != null || p.ircNick != null; } + public static bool IsSuper(Player p) { return p == null || p.SuperUser; } } } diff --git a/MCGalaxy/Player/Player.Handlers.cs b/MCGalaxy/Player/Player.Handlers.cs index bf3d1fe84..796890b4a 100644 --- a/MCGalaxy/Player/Player.Handlers.cs +++ b/MCGalaxy/Player/Player.Handlers.cs @@ -30,7 +30,7 @@ using MCGalaxy.SQL; using MCGalaxy.Maths; namespace MCGalaxy { - public sealed partial class Player : IDisposable { + public partial class Player : IDisposable { bool removedFromPending = false; internal void RemoveFromPending() { diff --git a/MCGalaxy/Player/Player.Login.cs b/MCGalaxy/Player/Player.Login.cs index d71bb6cd4..0aac66b68 100644 --- a/MCGalaxy/Player/Player.Login.cs +++ b/MCGalaxy/Player/Player.Login.cs @@ -26,7 +26,7 @@ using MCGalaxy.Tasks; using MCGalaxy.Maths; namespace MCGalaxy { - public sealed partial class Player : IDisposable { + public partial class Player : IDisposable { void HandleLogin(byte[] packet) { LastAction = DateTime.UtcNow; diff --git a/MCGalaxy/Player/Player.cs b/MCGalaxy/Player/Player.cs index c2f7564ac..93b3b94e8 100644 --- a/MCGalaxy/Player/Player.cs +++ b/MCGalaxy/Player/Player.cs @@ -33,7 +33,7 @@ namespace MCGalaxy { public string username { get; set; } } - public sealed partial class Player : Entity, IDisposable { + public partial class Player : Entity, IDisposable { static int sessionCounter; @@ -45,6 +45,7 @@ namespace MCGalaxy { DisplayName = playername; SessionID = Interlocked.Increment(ref sessionCounter) & SessionIDMask; spamChecker = new SpamChecker(this); + SuperUser = true; } public Player(Socket s) {