diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 0c2c0f3e..f1ce0005 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1232,82 +1232,6 @@ namespace TShockAPI return; } - // TODO: Remove from bouncer (does't look like Bouncer code) - if (args.Player.AwaitingName) - { - 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; - } - - - // TODO: REMOVE. This does NOT look like Bouncer code. - 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) - { - if (includeUnprotected) - args.Player.SendInfoMessage("There are no regions at this point."); - else - args.Player.SendInfoMessage("There are no regions at this point or they are not protected."); - } - else - { - 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, 4); - args.Handled = true; - return; - } - - // TODO: REMOVE. This does NOT look like Bouncer code. - if (args.Player.AwaitingTempPoint > 0) - { - args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].X = tileX; - args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].Y = tileY; - args.Player.SendInfoMessage("Set temp point {0}.", args.Player.AwaitingTempPoint); - args.Player.SendTileSquare(tileX, tileY, 4); - args.Player.AwaitingTempPoint = 0; - args.Handled = true; - return; - } - Item selectedItem = args.Player.SelectedItem; int lastKilledProj = args.Player.LastKilledProjectile; ITile tile = Main.tile[tileX, tileY]; diff --git a/TShockAPI/DB/RegionManager.cs b/TShockAPI/DB/RegionManager.cs index 34a52f8e..3d5bea77 100644 --- a/TShockAPI/DB/RegionManager.cs +++ b/TShockAPI/DB/RegionManager.cs @@ -26,6 +26,9 @@ using Microsoft.Xna.Framework; namespace TShockAPI.DB { + /// + /// Represents the Region database manager. + /// public class RegionManager { /// diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index baea2f82..d8c47b3b 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -3133,11 +3133,6 @@ namespace TShockAPI return true; } - if (!TShock.Config.RegionProtectGemLocks) - { - return false; - } - return false; } diff --git a/TShockAPI/RegionHandler.cs b/TShockAPI/RegionHandler.cs new file mode 100644 index 00000000..b3972fc1 --- /dev/null +++ b/TShockAPI/RegionHandler.cs @@ -0,0 +1,197 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2018 Pryaxis & TShock Contributors +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using TShockAPI.DB; +using TShockAPI.Hooks; + +namespace TShockAPI +{ + /// + /// Represents TShock's Region subsystem. This subsystem is in charge of executing region related logic, such as + /// setting temp points or invoking region events. + /// + internal sealed class RegionHandler : IDisposable + { + private readonly RegionManager _regionManager; + + /// + /// Initializes a new instance of the class with the specified instance. + /// + /// The instance. + public RegionHandler(RegionManager regionManager) + { + _regionManager = regionManager; + + GetDataHandlers.GemLockToggle += OnGemLockToggle; + GetDataHandlers.PlayerUpdate += OnPlayerUpdate; + GetDataHandlers.TileEdit += OnTileEdit; + } + + /// + /// Disposes the region handler. + /// + public void Dispose() + { + GetDataHandlers.GemLockToggle -= OnGemLockToggle; + GetDataHandlers.PlayerUpdate -= OnPlayerUpdate; + GetDataHandlers.TileEdit -= OnTileEdit; + } + + private void OnGemLockToggle(object sender, GetDataHandlers.GemLockToggleEventArgs e) + { + if (TShock.Config.RegionProtectGemLocks) + { + e.Handled = true; + } + } + + private void OnPlayerUpdate(object sender, GetDataHandlers.PlayerUpdateEventArgs e) + { + var player = e.Player; + + // Store the player's last known region and update the current based on known regions at their coordinates. + var oldRegion = player.CurrentRegion; + player.CurrentRegion = _regionManager.GetTopRegion(_regionManager.InAreaRegion(player.TileX, player.TileY)); + + // Do not fire any hooks if the player has not left and/or entered a region. + if (player.CurrentRegion == oldRegion) + { + return; + } + + // Ensure that the player has left a region before invoking the RegionLeft event + if (oldRegion != null) + { + RegionHooks.OnRegionLeft(player, oldRegion); + } + + // Ensure that the player has entered a valid region before invoking the RegionEntered event + if (player.CurrentRegion != null) + { + RegionHooks.OnRegionEntered(player, player.CurrentRegion); + } + } + + private void OnTileEdit(object sender, GetDataHandlers.TileEditEventArgs e) + { + var player = e.Player; + + #region Region Information Display + + if (player.AwaitingName) + { + bool includeUnprotected = false; + bool includeZIndexes = false; + bool persistentMode = false; + + foreach (string nameParameter in player.AwaitingNameParameters) + { + // If this flag is passed the final output will include unprotected regions, i.e regions + // that have the DisableBuild flag set to false + if (nameParameter.Equals("-u", StringComparison.InvariantCultureIgnoreCase)) + { + includeUnprotected = true; + } + + // If this flag is passed the final output will include a region's Z index + if (nameParameter.Equals("-z", StringComparison.InvariantCultureIgnoreCase)) + { + includeZIndexes = true; + } + + // If this flag is passed the player will continue to receive region information upon editing tiles + if (nameParameter.Equals("-p", StringComparison.InvariantCultureIgnoreCase)) + { + persistentMode = true; + } + } + + var output = new List(); + foreach (Region region in _regionManager.Regions.OrderBy(r => r.Z).Reverse()) + { + // Ensure that the specified tile is region protected + if (e.X < region.Area.Left || e.X > region.Area.Right) + { + continue; + } + + if (e.Y < region.Area.Top || e.Y > region.Area.Bottom) + { + continue; + } + + // Do not include the current region if it has not been protected and the includeUnprotected flag has not been set + if (!region.DisableBuild && !includeUnprotected) + { + continue; + } + + output.Add($"{region.Name} {(includeZIndexes ? $"(Z:{region.Z}" : string.Empty)}"); + } + + if (output.Count == 0) + { + player.SendInfoMessage(includeUnprotected + ? "There are no regions at this point." + : "There are no regions at this point, or they are not protected."); + } + else + { + player.SendInfoMessage(includeUnprotected ? "Regions at this point: " : "Protected regions at this point: "); + + foreach (string line in PaginationTools.BuildLinesFromTerms(output)) + { + player.SendMessage(line, Color.White); + } + } + + if (!persistentMode) + { + player.AwaitingName = false; + player.AwaitingNameParameters = null; + } + + // Revert all tile changes and handle the event + player.SendTileSquare(e.X, e.Y, 4); + e.Handled = true; + } + + #endregion + + #region TempPoints Setup + + if (player.AwaitingTempPoint != 0) + { + // Set temp point coordinates to current tile coordinates + player.TempPoints[player.AwaitingTempPoint - 1].X = e.X; + player.TempPoints[player.AwaitingTempPoint - 1].Y = e.Y; + player.SendInfoMessage($"Set temp point {player.AwaitingTempPoint}."); + + // Reset the awaiting temp point + player.AwaitingTempPoint = 0; + + // Revert all tile changes and handle the event + player.SendTileSquare(e.X, e.Y, 4); + e.Handled = true; + } + + #endregion + } + } +} diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index b851e720..f839019d 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -134,6 +134,11 @@ namespace TShockAPI /// The TShock anti-cheat/anti-exploit system. internal Bouncer Bouncer; + /// + /// TShock's Region subsystem. + /// + internal RegionHandler RegionSystem; + /// /// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded. /// @@ -319,6 +324,7 @@ namespace TShockAPI RestManager = new RestManager(RestApi); RestManager.RegisterRestfulCommands(); Bouncer = new Bouncer(); + RegionSystem = new RegionHandler(Regions); var geoippath = "GeoIP.dat"; if (Config.EnableGeoIP && File.Exists(geoippath)) @@ -430,6 +436,8 @@ namespace TShockAPI RestApi.Dispose(); Log.Dispose(); + + RegionSystem.Dispose(); } base.Dispose(disposing); } @@ -1133,22 +1141,6 @@ namespace TShockAPI player.SendErrorMessage($"You are holding a banned item: {player.TPlayer.inventory[player.TPlayer.selectedItem].Name}"); } } - - var oldRegion = player.CurrentRegion; - player.CurrentRegion = Regions.GetTopRegion(Regions.InAreaRegion(player.TileX, player.TileY)); - - if (oldRegion != player.CurrentRegion) - { - if (oldRegion != null) - { - RegionHooks.OnRegionLeft(player, oldRegion); - } - - if (player.CurrentRegion != null) - { - RegionHooks.OnRegionEntered(player, player.CurrentRegion); - } - } } } Utils.SetConsoleTitle(false); diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 230443c0..b3deaaea 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -96,6 +96,7 @@ + @@ -192,6 +193,7 @@ TerrariaServerAPI + @@ -203,7 +205,7 @@ - +