using System; using System.Collections.Generic; using MCGalaxy; using MCGalaxy.Blocks; using MCGalaxy.Commands; using MCGalaxy.DB; using MCGalaxy.Drawing.Ops; using MCGalaxy.Events.PlayerEvents; using MCGalaxy.Network; using BlockID = System.UInt16; namespace MCGalaxy { public sealed class PluginHigherlight : Plugin { public override string name { get { return "Higherlight"; } } public override string MCGalaxy_Version { get { return "1.9.4.9"; } } public override string creator { get { return "Goodly"; } } public static Command highlight; public static Command2 higherlightCmd; public static BlockID[] highlightBlocks = new BlockID[] { 425, 426 }; //Portal and Message block NA2 server-side IDs public override void Load(bool startup) { HighlightDrawOp.DefaultPlaceHighlight = highlightBlocks[0]; HighlightDrawOp.DefaultDeleteHighlight = highlightBlocks[1]; highlight = Command.Find("highlight"); higherlightCmd = new CmdHigherlight(); Command.Register(higherlightCmd); OnPlayerCommandEvent.Register(OnPlayerCommand, Priority.Low); } public override void Unload(bool shutdown) { HighlightDrawOp.DefaultPlaceHighlight = Block.Green; HighlightDrawOp.DefaultDeleteHighlight = Block.Red; Command.Unregister(higherlightCmd); OnPlayerCommandEvent.Unregister(OnPlayerCommand); } void OnPlayerCommand(Player p, string cmd, string args, CommandData data) { if (cmd.CaselessEq("highlight")) { p.cancelcommand = true; higherlightCmd.Use(p, args); p.lastCMD = cmd + " " + args; Logger.Log(LogType.CommandUsage, "{0} used /{1} {2}", p.name, cmd, args); return; } if (cmd.CaselessEq("help")) { //Doesn't catch aliases.txt :/ if (!(args.CaselessEq(highlight.name) || args.CaselessEq(highlight.shortcut))) return; p.cancelcommand = true; higherlightCmd.Help(p); p.lastCMD = cmd + " " + args; Logger.Log(LogType.CommandUsage, "{0} used /{1} {2}", p.name, cmd, args); return; } } } public class CmdHigherlight : Command2 { public override string name { get { return "Higherlight"; } } public override string shortcut { get { return "hl2"; } } public override bool MessageBlockRestricted { get { return true; } } public override string type { get { return "Moderation"; } } public override bool museumUsable { get { return false; } } public override LevelPermission defaultRank { get { return LevelPermission.Admin; } } const string xrayFlag = " xray"; public override void Use(Player p, string message, CommandData data) { if (message.Length == 0) { Help(p); return; } bool xray = false; if (message.CaselessEnds(xrayFlag)) { xray = true; message = message.Substring(0, message.Length - xrayFlag.Length); } if (!ValidateHighlightInput(p, message)) return; if (xray) AddZone(p); DarkenBlocks(p, xray); ReplaceExistingHighlightBlocks(p, 0, 0, 0, p.level.MaxX, p.level.MaxY, p.level.MaxZ, 0, 0, 0); PluginHigherlight.highlight.Use(p, message, data); CommandData data2 = data; data2.Context = CommandContext.MessageBlock; Command.Find("script").Use(p, "utils #darken", data2); p.Message("Use %b/reload %Sto fix blocks and environment colors."); } /// /// Duplicates the cmd parsing checks from original hl command /// static bool ValidateHighlightInput(Player p, string message) { string[] words = message.SplitSpaces(); if (words.Length >= 2) { TimeSpan unused = new TimeSpan(); if (!CommandParser.GetTimespan(p, words[1], ref unused, "highlight the past", "s")) return false; } words[0] = PlayerDB.MatchNames(p, words[0]); if (words[0] == null) return false; return true; } static void DarkenBlocks(Player p, bool xray) { BlockDefinition[] defs = p.level.CustomBlockDefs; List buffer = new List(); for (int i = 0; i < defs.Length; i++) { if (defs[i] == null) continue; bool act = true; foreach (BlockID b in PluginHigherlight.highlightBlocks) { if (i == b) { act = false; break; } } if (!act) { continue; } if (!xray && defs[i].FullBright == false) { continue; } BlockDefinition copy = defs[i].Copy(); copy.FullBright = false; copy.UseLampBrightness = false; copy.Brightness = 0; if (xray) { copy.BlockDraw = 4; //preserve map edge collision if (copy.RawID != Block.Bedrock) { copy.CollideType = 0; } } p.Send(Packet.DefineBlockExt(copy, true, true, true, true)); //buffer.AddRange(Packet.DefineBlockExt(copy, true, true, true, true)); } //doesn't work for some reason //p.Send(buffer.ToArray()); } static void AddZone(Player p) { var min = new Maths.Vec3U16(0, 0, 0); var max = new Maths.Vec3U16(p.level.Width, p.level.Height, p.level.Length); //Invert max and min so the line is inside the bedrock p.Send(Packet.MakeSelection(127, "map bounds", max, min, 0, 0, 0, 1, true)); } static void ReplaceExistingHighlightBlocks(Player p, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { int xLen = (x2 - x1) + 1; int yLen = (y2 - y1) + 1; int zLen = (z2 - z1) + 1; BufferedBlockSender buffer = new BufferedBlockSender(p); int index = 0; for (int yi = y3 + yLen - 1; yi >= y3; --yi) { for (int zi = z3; zi < z3 + zLen; ++zi) { for (int xi = x3; xi < x3 + xLen; ++xi) { bool place = false; foreach (BlockID b in PluginHigherlight.highlightBlocks) { if (p.level.GetBlock((ushort)xi, (ushort)yi, (ushort)zi) == b) { place = true; break; } } if (!place) { continue; } int pos = p.level.PosToInt((ushort)xi, (ushort)yi, (ushort)zi); if (pos >= 0) buffer.Add(pos, Block.Obsidian); index++; } } } buffer.Flush(); } public override void Help(Player p) { p.Message("&T/Highlight [player] "); p.Message("&HHighlights blocks changed by [player] in the past "); p.Message("&H If is not given, highlights for last 30 minutes"); p.Message("&W/Highlight cannot be disabled, use /reload to un-highlight"); p.Message("&HAdd \"{0}\" to make all blocks except highlight invisible.", xrayFlag); } } }