Move Region related code into a separate subsystem

This commit is contained in:
Ivan 2018-04-29 18:33:07 +02:00
parent 8d45222af3
commit ec78a070a7
5 changed files with 201 additions and 93 deletions

View file

@ -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<string> outputRegions = new List<string>();
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];

View file

@ -26,6 +26,9 @@ using Microsoft.Xna.Framework;
namespace TShockAPI.DB
{
/// <summary>
/// Represents the Region database manager.
/// </summary>
public class RegionManager
{
/// <summary>

189
TShockAPI/RegionHandler.cs Normal file
View file

@ -0,0 +1,189 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Microsoft.Xna.Framework;
using TerrariaApi.Server;
using TShockAPI.DB;
using TShockAPI.Hooks;
namespace TShockAPI
{
/// <summary>
/// Represents TShock's Region subsystem. This subsystem is in charge of executing region related logic, such as
/// setting temp points.
/// </summary>
internal sealed class RegionHandler
{
private readonly RegionManager _regionManager;
private DateTime _lastCheck = DateTime.Now;
/// <summary>
/// Initializes a new instance of the <see cref="RegionHandler"/> class with the specified TShock instance and database connection.
/// </summary>
/// <param name="plugin">The <see cref="TShock"/> instance.</param>
/// <param name="connection">The database connection.</param>
public RegionHandler(TShock plugin, IDbConnection connection)
{
_regionManager = new RegionManager(connection);
GetDataHandlers.TileEdit += OnTileEdit;
ServerApi.Hooks.GameUpdate.Register(plugin, OnGameUpdate);
}
private void OnGameUpdate(EventArgs args)
{
// Do not perform checks unless enough time has passed since the last execution.
if ((DateTime.Now - _lastCheck).TotalSeconds < 1)
{
return;
}
foreach (var player in TShock.Players.Where(p => p?.Active == true))
{
// 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)
{
continue;
}
// 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);
}
}
// Set last execution time to this moment so we know when to execute the above code block again
_lastCheck = DateTime.Now;
}
private void OnTileEdit(object sender, GetDataHandlers.TileEditEventArgs e)
{
#region Region Information Display
if (e.Player.AwaitingName)
{
bool includeUnprotected = false;
bool includeZIndexes = false;
bool persistentMode = false;
foreach (string nameParameter in e.Player.AwaitingNameParameters)
{
// If this flag is passed the final output will include unprotected regions, i.e regions
// that do not 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<string>();
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.X > region.Area.Bottom)
{
continue;
}
// Do not include the current region if it has not been protected and the includeProtected flag has not been set
if (!region.DisableBuild && !includeUnprotected)
{
continue;
}
output.Add($"{region.Name} {(includeZIndexes ? $"(Z:{region.Z}" : string.Empty)}");
}
if (output.Count == 0)
{
e.Player.SendInfoMessage(includeUnprotected
? "There are no regions at this point."
: "There are no regions at this point, or they are not protected.");
}
else
{
e.Player.SendInfoMessage(includeUnprotected ? "Regions at this point: " : "Protected regions at this point: ");
foreach (string line in PaginationTools.BuildLinesFromTerms(output))
{
e.Player.SendMessage(line, Color.White);
}
}
if (!persistentMode)
{
e.Player.AwaitingName = false;
e.Player.AwaitingNameParameters = null;
}
// Revert all tile changes and handle the event
e.Player.SendTileSquare(e.X, e.Y, 4);
e.Handled = true;
}
#endregion
#region TempPoints Setup
if (e.Player.AwaitingTempPoint != 0)
{
// Set temp point coordinates to current tile coordinates
e.Player.TempPoints[e.Player.AwaitingTempPoint - 1].X = e.X;
e.Player.TempPoints[e.Player.AwaitingTempPoint - 1].Y = e.Y;
e.Player.SendInfoMessage($"Set temp point {e.Player.AwaitingTempPoint}.");
e.Player.AwaitingTempPoint = 0;
// Revert all tile changes and handle the event
e.Player.SendTileSquare(e.X, e.Y, 4);
e.Handled = true;
}
#endregion
}
}
}

View file

@ -136,6 +136,11 @@ namespace TShockAPI
/// <summary>The TShock anti-cheat/anti-exploit system.</summary>
internal Bouncer Bouncer;
/// <summary>
/// TShock's Region subsystem.
/// </summary>
internal RegionHandler RegionSystem;
/// <summary>
/// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded.
/// </summary>
@ -321,6 +326,7 @@ namespace TShockAPI
RestManager = new RestManager(RestApi);
RestManager.RegisterRestfulCommands();
Bouncer = new Bouncer();
RegionSystem = new RegionHandler(this, DB);
var geoippath = "GeoIP.dat";
if (Config.EnableGeoIP && File.Exists(geoippath))
@ -1144,22 +1150,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);

View file

@ -96,6 +96,7 @@
<Compile Include="Localization\EnglishLanguage.cs" />
<Compile Include="NetItem.cs" />
<Compile Include="PlayerData.cs" />
<Compile Include="RegionHandler.cs" />
<Compile Include="Sockets\LinuxTcpSocket.cs" />
<Compile Include="SqlLog.cs" />
<Compile Include="TextLog.cs" />
@ -193,6 +194,7 @@
<Name>TerrariaServerAPI</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
@ -204,7 +206,7 @@
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties BuildVersion_IncrementBeforeBuild="False" BuildVersion_StartDate="2011/6/17" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_BuildAction="Both" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" />
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.