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);
}
}
}