From c557b4128cbe454c9d235d57f728949f32e052c6 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 28 Jan 2018 13:14:35 +1100 Subject: [PATCH] Initial WIP on having zones show stuff. --- MCGalaxy/Commands/Moderation/ZoneCmds.cs | 105 ++++++++++++-------- MCGalaxy/Commands/World/PermissionCmds.cs | 38 +++---- MCGalaxy/CorePlugin/MiscHandlers.cs | 5 + MCGalaxy/Levels/AccessController.cs | 6 +- MCGalaxy/Levels/IO/Importers/LvlImporter.cs | 2 + MCGalaxy/Levels/Level.cs | 7 ++ MCGalaxy/Levels/Zone.cs | 45 +++++++-- MCGalaxy/util/Formatting/Matcher.cs | 7 ++ 8 files changed, 147 insertions(+), 68 deletions(-) diff --git a/MCGalaxy/Commands/Moderation/ZoneCmds.cs b/MCGalaxy/Commands/Moderation/ZoneCmds.cs index 16f2cc942..54e976b9e 100644 --- a/MCGalaxy/Commands/Moderation/ZoneCmds.cs +++ b/MCGalaxy/Commands/Moderation/ZoneCmds.cs @@ -25,7 +25,11 @@ namespace MCGalaxy.Commands.Moderation { public override string type { get { return CommandTypes.Moderation; } } public override bool museumUsable { get { return false; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } - + public override CommandAlias[] Aliases { + get { return new[] { new CommandAlias("ZRemove", "del"), new CommandAlias("ZDelete", "del"), + new CommandAlias("ZAdd"), new CommandAlias("ZEdit", "edit") }; } + } + public override void Use(Player p, string message) { string[] args = message.SplitSpaces(); if (message.Length == 0) { Help(p); return; } @@ -34,17 +38,25 @@ namespace MCGalaxy.Commands.Moderation { if (args.Length == 1) { Help(p); return; } CreateZone(p, args, 1); } else if (args[0].CaselessEq("del")) { - Player.Message(p, "Place a block where you would like to delete a zone."); - p.MakeSelection(1, null, DeleteZone); + if (args.Length == 1) { Help(p); return; } + DeleteZone(p, args); + } else if (args[0].CaselessEq("edit")) { + if (args.Length < 3) { Help(p); return; } + EditZone(p, args); } else { CreateZone(p, args, 0); } } void CreateZone(Player p, string[] args, int offset) { - Zone z = new Zone(p.level); + if (p.level.FindZoneExact(args[offset]) != null) { + Player.Message(p, "A zone with that name already exists. Use %T/zedit %Sto change it."); + return; + } + + Zone z = new Zone(p.level); z.Config.Name = args[offset]; - PermissionCmd.Do(p, args, offset + 1, false, z.Access); + if (!PermissionCmd.Do(p, args, offset + 1, false, z.Access)) return; Player.Message(p, "Creating zone " + z.ColoredName); Player.Message(p, "Place or break two blocks to determine the edges."); @@ -52,47 +64,60 @@ namespace MCGalaxy.Commands.Moderation { } bool AddZone(Player p, Vec3S32[] marks, object state, ExtBlock block) { - Zone z = (Zone)state; - z.MinX = (ushort)Math.Min(marks[0].X, marks[1].X); - z.MinY = (ushort)Math.Min(marks[0].Y, marks[1].Y); - z.MinZ = (ushort)Math.Min(marks[0].Z, marks[1].Z); - z.MaxX = (ushort)Math.Max(marks[0].X, marks[1].X); - z.MaxY = (ushort)Math.Max(marks[0].Y, marks[1].Y); - z.MaxZ = (ushort)Math.Max(marks[0].Z, marks[1].Z); + Zone zone = (Zone)state; + zone.MinX = (ushort)Math.Min(marks[0].X, marks[1].X); + zone.MinY = (ushort)Math.Min(marks[0].Y, marks[1].Y); + zone.MinZ = (ushort)Math.Min(marks[0].Z, marks[1].Z); + zone.MaxX = (ushort)Math.Max(marks[0].X, marks[1].X); + zone.MaxY = (ushort)Math.Max(marks[0].Y, marks[1].Y); + zone.MaxZ = (ushort)Math.Max(marks[0].Z, marks[1].Z); - p.level.Zones.Add(z); + p.level.Zones.Add(zone); p.level.Save(true); - Player.Message(p, "Created zone " + z.ColoredName); - return false; - } - - bool DeleteZone(Player p, Vec3S32[] marks, object state, ExtBlock block) { - Level lvl = p.level; - bool foundDel = false; - Vec3S32 P = marks[0]; - - for (int i = 0; i < lvl.Zones.Count; i++) { - Zone zn = lvl.Zones[i]; - if (P.X < zn.MinX || P.X > zn.MaxX || P.Y < zn.MinY || P.Y > zn.MaxY || P.Z < zn.MinZ || P.Z > zn.MaxZ) continue; - - if (!zn.Access.CheckDetailed(p)) { - Player.Message(p, "Hence, you cannot delete this zone."); - continue; - } - - lvl.Zones.RemoveAt(i); i--; - Player.Message(p, "Zone " + zn.ColoredName + " %sdeleted"); - foundDel = true; - } - - if (!foundDel) Player.Message(p, "No zones found to delete."); + Player.Message(p, "Created zone " + zone.ColoredName); return false; } + void DeleteZone(Player p, string[] args) { + Level lvl = p.level; + Zone zone = Matcher.FindZones(p, lvl, args[1]); + if (zone == null) return; + if (!zone.Access.CheckDetailed(p)) { + Player.Message(p, "Hence, you cannot delete this zone."); return; + } + + lvl.Zones.Remove(zone); + Player.Message(p, "Zone " + zone.ColoredName + " %Sdeleted"); + lvl.Save(); + } + + void EditZone(Player p, string[] args) { + Level lvl = p.level; + Zone zone = Matcher.FindZones(p, lvl, args[1]); + if (zone == null) return; + if (!zone.Access.CheckDetailed(p)) { + Player.Message(p, "Hence, you cannot edit this zone."); return; + } + + if (args[2].CaselessEq("col")) { + ColorDesc desc = default(ColorDesc); + if (!CommandParser.GetHex(p, args[3], ref desc)) return; + + zone.Config.ShowColor = args[3]; + zone.ShowAll(lvl); + } else if (args[2].CaselessEq("alpha")) { + if (!CommandParser.GetByte(p, args[3], "Alpha", ref zone.Config.ShowAlpha)) return; + zone.ShowAll(lvl); + } else if (!PermissionCmd.Do(p, args, 2, false, zone.Access)) { + return; + } + lvl.Save(true); + } + public override void Help(Player p) { - Player.Message(p, "%T/Zone add [name] %H- Creates a zone only [name] can build in"); - Player.Message(p, "%T/Zone add [rank] %H- Creates a zone only [rank]+ can build in"); - Player.Message(p, "%T/Zone del %H- Deletes the zone clicked"); + Player.Message(p, "%T/Zone add [name] %H- Creates a new zone"); + Player.Message(p, "%T/Zone del [name] %H- Deletes the given zone"); + Player.Message(p, "%T/Zone edit [name] [args] %H- Edits/Updates the given zone"); } } diff --git a/MCGalaxy/Commands/World/PermissionCmds.cs b/MCGalaxy/Commands/World/PermissionCmds.cs index 2451152b2..6e0e0ba2b 100644 --- a/MCGalaxy/Commands/World/PermissionCmds.cs +++ b/MCGalaxy/Commands/World/PermissionCmds.cs @@ -24,19 +24,22 @@ namespace MCGalaxy.Commands.World { public override bool museumUsable { get { return false; } } public override LevelPermission defaultRank { get { return LevelPermission.Operator; } } - public static void Do(Player p, string[] args, int offset, bool max, AccessController access) { + public static bool Do(Player p, string[] args, int offset, bool max, AccessController access) { for (int i = offset; i < args.Length; i++) { string arg = args[i]; if (arg[0] == '+' || arg[0] == '-') { - SetList(p, access, arg); + if (!SetList(p, access, arg)) return false; } else if (max) { Group grp = Matcher.FindRanks(p, arg); - if (grp != null) access.SetMax(p, grp); + if (grp == null) return false; + access.SetMax(p, grp); } else { Group grp = Matcher.FindRanks(p, arg); - if (grp != null) access.SetMin(p, grp); + if (grp == null) return false; + access.SetMin(p, grp); } } + return true; } protected void DoLevel(Player p, string message, bool visit) { @@ -58,20 +61,21 @@ namespace MCGalaxy.Commands.World { Do(p, args, offset, max, access); } - static void SetList(Player p, AccessController access, string name) { + static bool SetList(Player p, AccessController access, string name) { bool include = name[0] == '+'; string mode = include ? "whitelist" : "blacklist"; name = name.Substring(1); if (name.Length == 0) { - Player.Message(p, "You must provide a player name to {0}.", mode); return; + Player.Message(p, "You must provide a player name to {0}.", mode); + return false; } - if (!Formatter.ValidName(p, name, "player")) return; + if (!Formatter.ValidName(p, name, "player")) return false; name = PlayerInfo.FindMatchesPreferOnline(p, name); - if (name == null) return; + if (name == null) return false; if (p != null && name.CaselessEq(p.name)) { - Player.Message(p, "You cannot {0} yourself.", mode); return; + Player.Message(p, "You cannot {0} yourself.", mode); return false; } if (include) { @@ -79,8 +83,8 @@ namespace MCGalaxy.Commands.World { } else { access.Blacklist(p, name); } - } - + return true; + } protected void ShowHelp(Player p, string action, string action2) { Player.Message(p, "%T/{0} [level] [rank]", name); @@ -93,12 +97,12 @@ namespace MCGalaxy.Commands.World { Player.Message(p, "%HPrevents [name] from {0}ing, even if their rank can.", action2); } } - + public sealed class CmdPermissionBuild : PermissionCmd { public override string name { get { return "PerBuild"; } } + public override string shortcut { get { return "WBuild"; } } public override CommandAlias[] Aliases { - get { return new[] { new CommandAlias("WBuild"), new CommandAlias("WorldBuild"), - new CommandAlias("PerBuildMax", "-max") }; } + get { return new[] { new CommandAlias("WorldBuild"), new CommandAlias("PerBuildMax", "-max") }; } } public override CommandPerm[] ExtraPerms { get { return new[] { new CommandPerm(LevelPermission.Operator, "+ bypasses max build rank restriction") }; } @@ -110,9 +114,9 @@ namespace MCGalaxy.Commands.World { public sealed class CmdPermissionVisit : PermissionCmd { public override string name { get { return "PerVisit"; } } + public override string shortcut { get { return "WAccess"; } } public override CommandAlias[] Aliases { - get { return new[] { new CommandAlias("WAccess"), new CommandAlias("WorldAccess"), - new CommandAlias("PerVisitMax", "-max") }; } + get { return new[] { new CommandAlias("WorldAccess"), new CommandAlias("PerVisitMax", "-max") }; } } public override CommandPerm[] ExtraPerms { get { return new[] { new CommandPerm(LevelPermission.Operator, "+ bypasses max visit rank restriction") }; } @@ -120,5 +124,5 @@ namespace MCGalaxy.Commands.World { public override void Use(Player p, string message) { DoLevel(p, message, true); } public override void Help(Player p) { ShowHelp(p, "visit", "visit"); } - } + } } \ No newline at end of file diff --git a/MCGalaxy/CorePlugin/MiscHandlers.cs b/MCGalaxy/CorePlugin/MiscHandlers.cs index f62bd362b..63dbbdeec 100644 --- a/MCGalaxy/CorePlugin/MiscHandlers.cs +++ b/MCGalaxy/CorePlugin/MiscHandlers.cs @@ -56,6 +56,11 @@ namespace MCGalaxy.Core { p.SendCurrentEnvColors(); p.SendCurrentMapAppearance(); p.SendCurrentBlockPermissions(); + + // TODO: unshow old zones here?? + if (p.Supports(CpeExt.SelectionCuboid)) { + foreach (Zone zn in level.Zones) { zn.Show(p); } + } if (!level.Config.Guns && p.aiming) { p.aiming = false; diff --git a/MCGalaxy/Levels/AccessController.cs b/MCGalaxy/Levels/AccessController.cs index 53f2396d3..70270a90d 100644 --- a/MCGalaxy/Levels/AccessController.cs +++ b/MCGalaxy/Levels/AccessController.cs @@ -228,8 +228,9 @@ namespace MCGalaxy { Update(); Logger.Log(LogType.UserActivity, "{0} rank changed to {1} on {2}.", type, grp.Name, lvl.name); Chat.MessageLevel(lvl, type + " rank changed to " + grp.ColoredName + "%S."); - if (p != null && p.level != lvl) + if (p != null && p.level != lvl) { Player.Message(p, "{0} rank changed to {1} %Son {2}%S.", type, grp.ColoredName, ColoredName); + } } public override void OnListChanged(Player p, string name, bool whitelist, bool removedFromOpposite) { @@ -244,8 +245,9 @@ namespace MCGalaxy { Update(); Logger.Log(LogType.UserActivity, "{0} on {1}", msg, lvl.name); Chat.MessageLevel(lvl, msg); - if (p != null && p.level != lvl) + if (p != null && p.level != lvl) { Player.Message(p, "{0} on %S{1}", msg, ColoredName); + } } diff --git a/MCGalaxy/Levels/IO/Importers/LvlImporter.cs b/MCGalaxy/Levels/IO/Importers/LvlImporter.cs index afabcab14..7f2310e9b 100644 --- a/MCGalaxy/Levels/IO/Importers/LvlImporter.cs +++ b/MCGalaxy/Levels/IO/Importers/LvlImporter.cs @@ -159,6 +159,8 @@ namespace MCGalaxy.Levels.IO { string line = Encoding.UTF8.GetString(buffer, 0, size), key, value; PropertiesFile.ParseLine(line, '=', out key, out value); if (key == null) continue; + + value = value.Trim(); ConfigElement.Parse(elems, key, value, z.Config); } diff --git a/MCGalaxy/Levels/Level.cs b/MCGalaxy/Levels/Level.cs index c3c348a5f..d0cd5ecf1 100644 --- a/MCGalaxy/Levels/Level.cs +++ b/MCGalaxy/Levels/Level.cs @@ -103,6 +103,13 @@ namespace MCGalaxy { if (Config.MOTD != "ignore") return Config.MOTD; return String.IsNullOrEmpty(p.group.MOTD) ? ServerConfig.MOTD : p.group.MOTD; } + + public Zone FindZoneExact(string name) { + foreach (Zone zone in Zones) { + if (zone.Config.Name.CaselessEq(name)) return zone; + } + return null; + } /// Whether block changes made on this level should be saved to the BlockDB and .lvl files. public bool ShouldSaveChanges() { diff --git a/MCGalaxy/Levels/Zone.cs b/MCGalaxy/Levels/Zone.cs index ab8ecfeee..ac75f0b1e 100644 --- a/MCGalaxy/Levels/Zone.cs +++ b/MCGalaxy/Levels/Zone.cs @@ -18,16 +18,22 @@ using System; using System.Collections.Generic; using MCGalaxy.Config; +using MCGalaxy.Network; +using MCGalaxy.Maths; namespace MCGalaxy { public sealed class ZoneConfig : AreaConfig { [ConfigString("Name", "General", "", true)] public string Name = ""; + [ConfigString("ShowColor", "General", "", true)] + public string ShowColor = ""; + [ConfigByte("ShowAlpha", "General", 0)] + public byte ShowAlpha = 0; public string Color { get { return Group.GetColor(BuildMin); } } - } - + } + /// Encapuslates build access permissions for a zone. public sealed class ZoneAccessController : AccessController { @@ -47,7 +53,7 @@ namespace MCGalaxy { get { return cfg.BuildMax; } set { cfg.BuildMax = value; } } - public override List Whitelisted { get { return cfg.BuildWhitelist; } } + public override List Whitelisted { get { return cfg.BuildWhitelist; } } public override List Blacklisted { get { return cfg.BuildBlacklist; } } protected override string ColoredName { get { return "zone " + cfg.Color + cfg.Name; } } @@ -59,9 +65,10 @@ namespace MCGalaxy { public override void OnPermissionChanged(Player p, Group grp, string type) { Update(); Logger.Log(LogType.UserActivity, "{0} rank changed to {1} in zone {2}.", type, grp.Name, cfg.Name); - Chat.MessageLevel(lvl, type + " rank changed to " + grp.ColoredName + "%S."); - if (p != null && p.level != lvl) + Chat.MessageLevel(lvl, type + " rank changed to " + grp.ColoredName + " %Sin zone " + cfg.Color + cfg.Name); + if (p != null && p.level != lvl) { Player.Message(p, "{0} rank changed to {1} %Sin {2}%S.", type, grp.ColoredName, ColoredName); + } } public override void OnListChanged(Player p, string name, bool whitelist, bool removedFromOpposite) { @@ -74,10 +81,11 @@ namespace MCGalaxy { Update(); Logger.Log(LogType.UserActivity, "{0} in zone {1}", msg, cfg.Name); - Chat.MessageLevel(lvl, msg); - if (p != null && p.level != lvl) + Chat.MessageLevel(lvl, msg + " in zone " + cfg.Color + cfg.Name); + if (p != null && p.level != lvl) { Player.Message(p, "{0} in %S{1}", msg, ColoredName); - } + } + } void Update() { lvl.Save(true); } } @@ -85,6 +93,7 @@ namespace MCGalaxy { public class Zone { public ushort MinX, MinY, MinZ; public ushort MaxX, MaxY, MaxZ; + public byte ID; public ZoneConfig Config; public ZoneAccessController Access; @@ -95,10 +104,28 @@ namespace MCGalaxy { } public bool CoversMap(Level lvl) { - return MinX == 0 && MinY == 0 && MinZ == 0 && + return MinX == 0 && MinY == 0 && MinZ == 0 && MaxX == lvl.Width - 1 && MaxY == lvl.Height - 1 && MaxZ == lvl.Length - 1; } + public bool Shows { get { return Config.ShowAlpha != 0 && Config.ShowColor != ""; } } + public void Show(Player p) { + if (!p.Supports(CpeExt.SelectionCuboid) || !Shows) return; + + ColorDesc col = Colors.ParseHex(Config.ShowColor); + p.Send(Packet.MakeSelection( + ID, "", new Vec3U16(MinX, MinY, MinZ), + new Vec3U16((ushort)(MaxX + 1), (ushort)(MaxY + 1), (ushort)(MaxZ + 1)), + col.R, col.G, col.B, Config.ShowAlpha, p.hasCP437)); + } + + public void ShowAll(Level lvl) { + Player[] players = PlayerInfo.Online.Items; + foreach (Player p in players) { + if (p.level == lvl) Show(p); + } + } + public Zone(Level lvl) { Config = new ZoneConfig(); Access = new ZoneAccessController(lvl, Config); diff --git a/MCGalaxy/util/Formatting/Matcher.cs b/MCGalaxy/util/Formatting/Matcher.cs index a9ce1e66f..11753a7c0 100644 --- a/MCGalaxy/util/Formatting/Matcher.cs +++ b/MCGalaxy/util/Formatting/Matcher.cs @@ -87,6 +87,13 @@ namespace MCGalaxy { null, wp => wp.Name, group); } + /// Find partial matches of 'name' against the list of zones in a map. + public static Zone FindZones(Player p, Level lvl, string name) { + int matches = 0; + return Find(p, name, out matches, lvl.Zones, + null, z => z.Config.Name, "zones"); + } + /// Finds partial matches of 'name' against the names of the items in the 'items' enumerable. /// If exactly one match, the matching item.