From 7b2a4494b547cfd81f006bb79df28f43a1cf3819 Mon Sep 17 00:00:00 2001 From: Lucas Nicodemus Date: Fri, 22 Dec 2017 01:16:18 -0700 Subject: [PATCH] Move ice tile processing to TSPlayer. This moves ice tile placement and processing from TShock.CheckTilePermissions to TSPlayer in the form of the new boolean 'HasModifiedIceSuccessfully.' This is such a stupid thing we have to track, but we have to track it. Previously, we duplicated all of the check permission code and inserted special ice code paths. This duplicated a ton of code for little gain. The result of moving everything is that the control flow is easier to follow. In Terraria ice tiles are placed and melt on a timer so it's necessary to track them being placed and removed to permit tile events that would otherwise be blocked due to region checks and stuff. They're usually fairly harmless blocks, and without this code, ice wouldn't work properly. It's not ideal for this to be in TShock at all. --- TShockAPI/Bouncer.cs | 6 ++- TShockAPI/TSPlayer.cs | 40 ++++++++++++++++++++ TShockAPI/TShock.cs | 85 ------------------------------------------- 3 files changed, 44 insertions(+), 87 deletions(-) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 0bbf77e5..77d602a7 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1146,7 +1146,8 @@ namespace TShockAPI { for (int j = y; j < y + tileData.Height; j++) { - if (TShock.CheckTilePermission(args.Player, i, j, type, EditAction.PlaceTile)) + if (!args.Player.HasModifiedIceSuccessfully(i, j, type, EditAction.PlaceTile) + && !args.Player.HasBuildPermission(i, j)) { args.Player.SendTileSquare(i, j, 4); args.Handled = true; @@ -1477,7 +1478,8 @@ namespace TShockAPI return; } - if (TShock.CheckTilePermission(args.Player, tileX, tileY, editData, action)) + if (!args.Player.HasModifiedIceSuccessfully(tileX, tileY, editData, action) + && !args.Player.HasBuildPermission(tileX, tileY)) { args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 05d9844c..a5aa17f2 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -385,6 +385,46 @@ namespace TShockAPI return HasBuildPermission(x, y) || HasPermission(Permissions.canpaint); } + /// Checks if a player can place ice, and if they can, tracks ice placements and removals. + /// The x coordinate of the suspected ice block. + /// The y coordinate of the suspected ice block. + /// The tile type of the suspected ice block. + /// The EditAction on the suspected ice block. + /// True if a player successfully places an ice tile or removes one of their past ice tiles. + public bool HasModifiedIceSuccessfully(int x, int y, short tileType, GetDataHandlers.EditAction editAction) + { + // The goal is to short circuit ASAP. + // A subsequent call to HasBuildPermission can figure this out if not explicitly ice. + if (!TShock.Config.AllowIce) + { + return false; + } + + // They've placed some ice. Horrible! + if (editAction == GetDataHandlers.EditAction.PlaceTile && tileType == TileID.MagicalIceBlock) + { + IceTiles.Add(new Point(x, y)); + return true; + } + + // The edit wasn't an add, so we check to see if the position matches any of the known ice tiles + if (editAction == GetDataHandlers.EditAction.KillTile) + { + foreach (Point p in IceTiles) + { + // If they're trying to kill ice or dirt, and the tile was in the list, we allow it. + if (p.X == x && p.Y == y && (Main.tile[p.X, p.Y].type == TileID.Dirt || Main.tile[p.X, p.Y].type == TileID.MagicalIceBlock)) + { + IceTiles.Remove(p); + return true; + } + } + } + + // Only a small number of cases let this happen. + return false; + } + /// /// A list of points where ice tiles have been placed. /// diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index f35efda8..5c03f7ee 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1757,91 +1757,6 @@ namespace TShockAPI e.Handled = true; } - /// CheckTilePermission - Checks to see if a player has permission to modify a tile in general. - /// player - The TSPlayer object. - /// tileX - The x coordinate of the tile. - /// tileY - The y coordinate of the tile. - /// tileType - The tile type. - /// actionType - The type of edit that took place. - /// bool - True if the player should not be able to modify a tile. - public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY, short tileType, GetDataHandlers.EditAction actionType) - { - if (!player.HasPermission(Permissions.canbuild)) - { - if (TShock.Config.AllowIce && actionType != GetDataHandlers.EditAction.PlaceTile) - { - foreach (Point p in player.IceTiles) - { - if (p.X == tileX && p.Y == tileY && (Main.tile[p.X, p.Y].type == 0 || Main.tile[p.X, p.Y].type == 127)) - { - player.IceTiles.Remove(p); - return false; - } - } - - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) - { - player.SendErrorMessage("You do not have permission to build!"); - player.BPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - return true; - } - - if (TShock.Config.AllowIce && actionType == GetDataHandlers.EditAction.PlaceTile && tileType == 127) - { - player.IceTiles.Add(new Point(tileX, tileY)); - return false; - } - - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) - { - player.SendErrorMessage("You do not have permission to build!"); - player.BPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - return true; - } - - if (!Regions.CanBuild(tileX, tileY, player)) - { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000) - { - player.SendErrorMessage("This region is protected from changes."); - player.RPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - return true; - } - - if (Config.DisableBuild) - { - if (!player.HasPermission(Permissions.antibuild)) - { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) - { - player.SendErrorMessage("The world is protected from changes."); - player.WPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - return true; - } - } - - if (Config.SpawnProtection) - { - if (!player.HasPermission(Permissions.editspawn)) - { - if (Utils.IsInSpawn(tileX, tileY)) - { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 2000) - { - player.SendErrorMessage("Spawn is protected from changes."); - player.SPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - return true; - } - } - } - return false; - } - /// Distance - Determines the distance between two vectors. /// value1 - The first vector location. /// value2 - The second vector location.