diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 2e9a7b17..57e4308b 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -24,7 +24,7 @@ using System.IO; using System.Linq; using System.Net; using System.Text; -using System.Threading; +using System.Threading; using TShockAPI.PluginUpdater; using Terraria; using TShockAPI.DB; @@ -2577,6 +2577,7 @@ namespace TShockAPI { args.Player.SendMessage("Hit a block to get the name of the region", Color.Yellow); args.Player.AwaitingName = true; + args.Player.AwaitingNameParameters = args.Parameters.Skip(1).ToArray(); } break; } @@ -2592,7 +2593,7 @@ namespace TShockAPI } else { - args.Player.SendMessage("Invalid syntax! Proper syntax: /region set [1/2]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region set <1/2>", Color.Red); } break; } @@ -2626,7 +2627,7 @@ namespace TShockAPI } } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region define [name]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region define ", Color.Red); break; } case "protect": @@ -2649,10 +2650,10 @@ namespace TShockAPI args.Player.SendMessage("Could not find specified region", Color.Red); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region protect [name] [true/false]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region protect ", Color.Red); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region protect [name] [true/false]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region protect ", Color.Red); break; } case "delete": @@ -2666,7 +2667,7 @@ namespace TShockAPI args.Player.SendMessage("Could not find specified region", Color.Red); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region delete [name]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region delete ", Color.Red); break; } case "clear": @@ -2710,7 +2711,7 @@ namespace TShockAPI } } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region allow [name] [region]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region allow ", Color.Red); break; } case "remove": @@ -2745,7 +2746,7 @@ namespace TShockAPI } } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region remove [name] [region]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region remove ", Color.Red); break; case "allowg": { @@ -2780,7 +2781,7 @@ namespace TShockAPI } } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region allow [group] [region]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region allowg ", Color.Red); break; } case "removeg": @@ -2815,7 +2816,7 @@ namespace TShockAPI } } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region removeg [group] [region]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region removeg ", Color.Red); break; case "list": { @@ -2844,16 +2845,27 @@ namespace TShockAPI { if (args.Parameters.Count > 1) { + if (args.Parameters.Count > 4) + { + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region info [-d] [page]"); + break; + } + string regionName = args.Parameters[1]; + bool displayBoundaries = args.Parameters.Skip(2).Any( + p => p.Equals("-d", StringComparison.InvariantCultureIgnoreCase) + ); + Region region = TShock.Regions.GetRegionByName(regionName); if (region == null) { - args.Player.SendErrorMessage("Region {0} does not exist.", regionName); + args.Player.SendErrorMessage("Region \"{0}\" does not exist.", regionName); break; } + int pageNumberIndex = displayBoundaries ? 3 : 2; int pageNumber; - if (!PaginationTools.TryParsePageNumber(args.Parameters, 2, args.Player, out pageNumber)) + if (!PaginationTools.TryParsePageNumber(args.Parameters, pageNumberIndex, args.Player, out pageNumber)) break; List lines = new List @@ -2900,10 +2912,42 @@ namespace TShockAPI FooterFormat = "Type /region info {0} for more information." } ); + + if (displayBoundaries) + { + Rectangle regionArea = region.Area; + foreach (Point boundaryPoint in Utils.Instance.EnumerateRegionBoundaries(regionArea)) + { + // Preferring dotted lines as those should easily be distinguishable from actual wires. + if ((boundaryPoint.X + boundaryPoint.Y & 1) == 0) + { + // Could be improved by sending raw tile data to the client instead but not really + // worth the effort as chances are very low that overwriting the wire for a few + // nanoseconds will cause much trouble. + Tile tile = Main.tile[boundaryPoint.X, boundaryPoint.Y]; + bool oldWireState = tile.wire; + tile.wire = true; + + try { + args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1); + } finally { + tile.wire = oldWireState; + } + } + } + + new Timer((dummy) => { + foreach (Point boundaryPoint in Utils.Instance.EnumerateRegionBoundaries(regionArea)) + if ((boundaryPoint.X + boundaryPoint.Y & 1) == 0) + args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1); + }, + null, 5000, Timeout.Infinite + ); + } } else { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region info [name]"); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region info "); } break; @@ -2922,10 +2966,10 @@ namespace TShockAPI args.Player.SendMessage("Could not find specified region", Color.Red); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region z [name] [#]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region z <#>", Color.Red); } else - args.Player.SendMessage("Invalid syntax! Proper syntax: /region z [name] [#]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /region z <#>", Color.Red); break; } case "resize": @@ -2975,13 +3019,13 @@ namespace TShockAPI } else { - args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize [regionname] [u/d/l/r] [amount]", + args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize ", Color.Red); } } else { - args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize [regionname] [u/d/l/r] [amount]1", + args.Player.SendMessage("Invalid syntax! Proper syntax: /region resize ", Color.Red); } break; @@ -2995,7 +3039,7 @@ namespace TShockAPI } if (args.Parameters.Count <= 1) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region tp [region]."); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /region tp ."); break; } @@ -3022,23 +3066,23 @@ namespace TShockAPI return; List lines = new List { - "set [1/2] - Sets the temporary region points.", + "set <1/2> - Sets the temporary region points.", "clear - Clears the temporary region points.", - "define [name] - Defines the region with the given name.", - "delete [name] - Deletes the given region.", - "name - Shows the name of the region at the given point.", + "define - Defines the region with the given name.", + "delete - Deletes the given region.", + "name [-u][-z][-p] - Shows the name of the region at the given point.", "list - Lists all regions.", - "resize [region] [u/d/l/r] [amount] - Resizes a region.", - "allow [user] [region] - Allows a user to a region.", - "remove [user] [region] - Removes a user from a region.", - "allowg [group] [region] - Allows a user group to a region.", - "removeg [group] [region] - Removes a user group from a region.", - "info [region] - Displays several information about the given region.", - "protect [name] [true/false] - Sets whether the tiles inside the region are protected or not.", - "z [name] [#] - Sets the z-order of the region.", + "resize - Resizes a region.", + "allow - Allows a user to a region.", + "remove - Removes a user from a region.", + "allowg - Allows a user group to a region.", + "removeg - Removes a user group from a region.", + "info [-d] - Displays several information about the given region.", + "protect - Sets whether the tiles inside the region are protected or not.", + "z <#> - Sets the z-order of the region.", }; if (args.Player.Group.HasPermission(Permissions.tp)) - lines.Add("tp [region] - Teleports you to the given region's center."); + lines.Add("tp - Teleports you to the given region's center."); PaginationTools.SendPage( args.Player, pageNumber, lines, diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 9b37250d..1cf7d702 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -17,11 +17,13 @@ along with this program. If not, see . */ using System; using System.Collections.Generic; -using System.ComponentModel; +using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.IO.Streams; using System.Linq; -using System.Text; +using System.Text; +using TShockAPI.DB; using Terraria; using TShockAPI.Net; @@ -1685,18 +1687,63 @@ namespace TShockAPI if (args.Player.AwaitingName) { - var protectedregions = TShock.Regions.InAreaRegionName(tileX, tileY); - if (protectedregions.Count == 0) + Debug.Assert(args.Player.AwaitingNameParameters != null); + + bool includeUnprotected = false; + bool includeZIndexes = false; + bool persistentMode = false; + foreach (string parameter in args.Player.AwaitingNameParameters) + { + if (parameter.Equals("-u", StringComparison.InvariantCultureIgnoreCase)) + includeUnprotected = true; + if (parameter.Equals("-z", StringComparison.InvariantCultureIgnoreCase)) + includeZIndexes = true; + if (parameter.Equals("-p", StringComparison.InvariantCultureIgnoreCase)) + persistentMode = true; + } + + List outputRegions = new List(); + foreach (Region region in TShock.Regions.Regions.OrderBy(r => r.Z).Reverse()) + { + if (!includeUnprotected && !region.DisableBuild) + continue; + if (tileX < region.Area.Left || tileX > region.Area.Right) + continue; + if (tileY < region.Area.Top || tileY > region.Area.Bottom) + continue; + + string format = "{1}"; + if (includeZIndexes) + format = "{1} (z:{0})"; + + outputRegions.Add(string.Format(format, region.Z, region.Name)); + } + + if (outputRegions.Count == 0) { - args.Player.SendMessage("Region is not protected", Color.Yellow); + if (includeUnprotected) + args.Player.SendMessage("There are no regions at this point.", Color.Yellow); + else + args.Player.SendMessage("There are no regions at this point or they are not protected.", Color.Yellow); } else { - string regionlist = string.Join(",", protectedregions.ToArray()); - args.Player.SendMessage("Region Name(s): " + regionlist, Color.Yellow); + if (includeUnprotected) + args.Player.SendSuccessMessage("Regions at this point:"); + else + args.Player.SendSuccessMessage("Protected regions at this point:"); + + foreach (string line in PaginationTools.BuildLinesFromTerms(outputRegions)) + args.Player.SendMessage(line, Color.White); } + + if (!persistentMode) + { + args.Player.AwaitingName = false; + args.Player.AwaitingNameParameters = null; + } + args.Player.SendTileSquare(tileX, tileY); - args.Player.AwaitingName = false; return true; } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index d9182329..986d3147 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -121,6 +121,8 @@ namespace TShockAPI public bool AwaitingName { get; set; } + public string[] AwaitingNameParameters { get; set; } + /// /// The last time a player broke a grief check. /// diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 8687ec4b..f98cb284 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -22,7 +22,8 @@ using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography; -using System.Text; +using System.Text; +using TShockAPI.DB; using Terraria; namespace TShockAPI @@ -841,5 +842,25 @@ namespace TShockAPI } return new string(returnstr); } + + /// + /// Enumerates boundary points of the given region's rectangle. + /// + /// The region's area to enumerate through. + /// The enumerated boundary points. + public IEnumerable EnumerateRegionBoundaries(Rectangle regionArea) + { + for (int x = 0; x < regionArea.Width + 1; x++) + { + yield return new Point(regionArea.Left + x, regionArea.Top); + yield return new Point(regionArea.Left + x, regionArea.Bottom); + } + + for (int y = 1; y < regionArea.Height; y++) + { + yield return new Point(regionArea.Left, regionArea.Top + y); + yield return new Point(regionArea.Right, regionArea.Top + y); + } + } } }