Improved spam detection for create and kill tiles.

Improved item use blocking with banned items.
Reserved slots should work now to 5 slots above max.
This commit is contained in:
Zidonuke 2011-12-27 12:02:07 -05:00
parent a766f1e5d9
commit 5c6d03f9af
5 changed files with 119 additions and 45 deletions

View file

@ -51,8 +51,6 @@ namespace TShockAPI
public bool RangeChecks = true; public bool RangeChecks = true;
[Description("Disables any building; placing of blocks")] [Description("Disables any building; placing of blocks")]
public bool DisableBuild; public bool DisableBuild;
[Description("Kick a player if they exceed this number of tile kills within 1 second.")]
public int TileThreshold = 120;
[Description("#.#.#. = Red/Blue/Green - RGB Colors for the Admin Chat Color. Max value: 255")] [Description("#.#.#. = Red/Blue/Green - RGB Colors for the Admin Chat Color. Max value: 255")]
public float[] SuperAdminChatRGB = { 255, 0, 0 }; public float[] SuperAdminChatRGB = { 255, 0, 0 };
[Description("Super admin group chat prefix")] [Description("Super admin group chat prefix")]
@ -177,10 +175,10 @@ namespace TShockAPI
[Description("Disables reporting of playercount to the stat system.")] [Description("Disables reporting of playercount to the stat system.")]
public bool DisablePlayerCountReporting = false; public bool DisablePlayerCountReporting = false;
[Description("Disables clown bomb projectiles from spawning")] //Change this to stop the tile from spawning [Description("Disables clown bomb projectiles from spawning")]
public bool DisableClownBombs = false; public bool DisableClownBombs = false;
[Description("Disables snow ball projectiles from spawning")] //Change this to stop the tile from spawning [Description("Disables snow ball projectiles from spawning")]
public bool DisableSnowBalls = false; public bool DisableSnowBalls = false;
[Description("Change ingame chat format, {0} = Group Name, {1} = Group Prefix, {2} = Player Name, {3} = Group Suffix, {4} = Chat Message")] [Description("Change ingame chat format, {0} = Group Name, {1} = Group Prefix, {2} = Player Name, {3} = Group Suffix, {4} = Chat Message")]
@ -188,6 +186,12 @@ namespace TShockAPI
[Description("Force the world time to be normal, day, or night")] [Description("Force the world time to be normal, day, or night")]
public string ForceTime = "normal"; public string ForceTime = "normal";
[Description("Disable/Revert a player if they exceed this number of tile kills within 1 second.")]
public int TileKillThreshold = 80;
[Description("Disable/Revert a player if they exceed this number of tile places within 1 second.")]
public int TilePlaceThreshold = 20;
public static ConfigFile Read(string path) public static ConfigFile Read(string path)
{ {

View file

@ -520,9 +520,17 @@ namespace TShockAPI
return true; return true;
} }
if (type == 0 && Main.tileSolid[Main.tile[tileX, tileY].type] && args.Player.Active) if(type == 1)
{ {
args.Player.TileThreshold++; args.Player.TilePlaceThreshold++;
var coords = new Vector2(tileX, tileY);
if (!args.Player.TilesCreated.ContainsKey(coords))
args.Player.TilesCreated.Add(coords, Main.tile[tileX, tileY]);
}
if ((type == 0 || type == 4) && Main.tileSolid[Main.tile[tileX, tileY].type])
{
args.Player.TileKillThreshold++;
var coords = new Vector2(tileX, tileY); var coords = new Vector2(tileX, tileY);
if (!args.Player.TilesDestroyed.ContainsKey(coords)) if (!args.Player.TilesDestroyed.ContainsKey(coords))
args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY]); args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY]);
@ -588,16 +596,6 @@ namespace TShockAPI
return true; return true;
} }
if ((control & 32) == 32)
{
if (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned(args.TPlayer.inventory[item].name))
{
args.Player.LastThreat = DateTime.UtcNow;
args.Player.SendMessage(string.Format("You cannot use {0} on this server. Your actions are being ignored.", args.TPlayer.inventory[item].name), Color.Red);
return true;
}
}
if (!pos.Equals(args.Player.LastNetPosition)) if (!pos.Equals(args.Player.LastNetPosition))
{ {
float distance = Vector2.Distance(new Vector2((pos.X / 16f), (pos.Y / 16f)), new Vector2(Main.spawnTileX, Main.spawnTileY)); float distance = Vector2.Distance(new Vector2((pos.X / 16f), (pos.Y / 16f)), new Vector2(Main.spawnTileX, Main.spawnTileY));
@ -623,9 +621,61 @@ namespace TShockAPI
return true; return true;
} }
} }
args.Player.LastNetPosition = pos; args.Player.LastNetPosition = pos;
return false;
if ((control & 32) == 32)
{
if (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned(args.TPlayer.inventory[item].name))
{
control -= 32;
args.Player.LastThreat = DateTime.UtcNow;
args.Player.SendMessage(string.Format("You cannot use {0} on this server. Your actions are being ignored.", args.TPlayer.inventory[item].name), Color.Red);
}
}
args.TPlayer.selectedItem = item;
args.TPlayer.position = pos;
args.TPlayer.velocity = vel;
args.TPlayer.oldVelocity = args.TPlayer.velocity;
args.TPlayer.fallStart = (int)(pos.Y / 16f);
args.TPlayer.controlUp = false;
args.TPlayer.controlDown = false;
args.TPlayer.controlLeft = false;
args.TPlayer.controlRight = false;
args.TPlayer.controlJump = false;
args.TPlayer.controlUseItem = false;
args.TPlayer.direction = -1;
if ((control & 1) == 1)
{
args.TPlayer.controlUp = true;
}
if ((control & 2) == 2)
{
args.TPlayer.controlDown = true;
}
if ((control & 4) == 4)
{
args.TPlayer.controlLeft = true;
}
if ((control & 8) == 8)
{
args.TPlayer.controlRight = true;
}
if ((control & 16) == 16)
{
args.TPlayer.controlJump = true;
}
if ((control & 32) == 32)
{
args.TPlayer.controlUseItem = true;
}
if ((control & 64) == 64)
{
args.TPlayer.direction = 1;
}
NetMessage.SendData((int)PacketTypes.PlayerUpdate, -1, args.Player.Index, "", args.Player.Index);
return true;
} }
private static bool HandleProjectileNew(GetDataHandlerArgs args) private static bool HandleProjectileNew(GetDataHandlerArgs args)

View file

@ -35,11 +35,13 @@ namespace TShockAPI
[Description("Prevents you from being reverted by kill tile abuse detection")] [Description("Prevents you from being reverted by kill tile abuse detection")]
public static readonly string ignorekilltiledetection; public static readonly string ignorekilltiledetection;
[Description("Prevents you from being reverted by place tile abuse detection")]
public static readonly string ignoreplacetiledetection;
[Description("Specific log messages are sent to users with this permission")] [Description("Specific log messages are sent to users with this permission")]
public static readonly string logs; public static readonly string logs;
[Todo] [Description("Allows you to bypass the max slots for up to 5 slots above your max")]
[Description("Not currently working")]
public static readonly string reservedslot; public static readonly string reservedslot;
[Description("User is notified when an update is available")] [Description("User is notified when an update is available")]

View file

@ -30,8 +30,10 @@ namespace TShockAPI
{ {
public static readonly TSServerPlayer Server = new TSServerPlayer(); public static readonly TSServerPlayer Server = new TSServerPlayer();
public static readonly TSPlayer All = new TSPlayer("All"); public static readonly TSPlayer All = new TSPlayer("All");
public int TileThreshold { get; set; } public int TileKillThreshold { get; set; }
public int TilePlaceThreshold { get; set; }
public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; } public Dictionary<Vector2, Tile> TilesDestroyed { get; protected set; }
public Dictionary<Vector2, Tile> TilesCreated { get; protected set; }
public bool SyncHP { get; set; } public bool SyncHP { get; set; }
public bool SyncMP { get; set; } public bool SyncMP { get; set; }
public Group Group { get; set; } public Group Group { get; set; }
@ -157,6 +159,7 @@ namespace TShockAPI
public TSPlayer(int index) public TSPlayer(int index)
{ {
TilesDestroyed = new Dictionary<Vector2, Tile>(); TilesDestroyed = new Dictionary<Vector2, Tile>();
TilesCreated = new Dictionary<Vector2, Tile>();
Index = index; Index = index;
Group = new Group("null"); Group = new Group("null");
} }
@ -164,6 +167,7 @@ namespace TShockAPI
protected TSPlayer(String playerName) protected TSPlayer(String playerName)
{ {
TilesDestroyed = new Dictionary<Vector2, Tile>(); TilesDestroyed = new Dictionary<Vector2, Tile>();
TilesCreated = new Dictionary<Vector2, Tile>();
Index = -1; Index = -1;
FakePlayer = new Player { name = playerName, whoAmi = -1 }; FakePlayer = new Player { name = playerName, whoAmi = -1 };
Group = new Group("null"); Group = new Group("null");
@ -419,17 +423,17 @@ namespace TShockAPI
NetMessage.SendData((int)PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection); NetMessage.SendData((int)PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection);
} }
public void RevertKillTile(Dictionary<Vector2, Tile> destroyedTiles) public void RevertTiles(Dictionary<Vector2, Tile> tiles)
{ {
// Update Main.Tile first so that when tile sqaure is sent it is correct // Update Main.Tile first so that when tile sqaure is sent it is correct
foreach (KeyValuePair<Vector2, Tile> entry in destroyedTiles) foreach (KeyValuePair<Vector2, Tile> entry in tiles)
{ {
Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value; Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value;
Log.Debug(string.Format("Reverted DestroyedTile(TileXY:{0}_{1}, Type:{2})", Log.Debug(string.Format("Reverted Tiles(TileXY:{0}_{1}, Type:{2})",
entry.Key.X, entry.Key.Y, Main.tile[(int)entry.Key.X, (int)entry.Key.Y].type)); entry.Key.X, entry.Key.Y, Main.tile[(int)entry.Key.X, (int)entry.Key.Y].type));
} }
// Send all players updated tile sqaures // Send all players updated tile sqaures
foreach (Vector2 coords in destroyedTiles.Keys) foreach (Vector2 coords in tiles.Keys)
{ {
All.SendTileSquare((int)coords.X, (int)coords.Y, 3); All.SendTileSquare((int)coords.X, (int)coords.Y, 3);
} }

View file

@ -472,16 +472,28 @@ namespace TShockAPI
count++; count++;
if (player.TilesDestroyed != null) if (player.TilesDestroyed != null)
{ {
if (player.TileThreshold >= Config.TileThreshold) if (player.TileKillThreshold >= Config.TileKillThreshold)
{ {
TSPlayer.Server.RevertKillTile(player.TilesDestroyed); TSPlayer.Server.RevertTiles(player.TilesDestroyed);
} }
if (player.TileThreshold > 0) if (player.TileKillThreshold > 0)
{ {
player.TileThreshold = 0; player.TileKillThreshold = 0;
player.TilesDestroyed.Clear(); player.TilesDestroyed.Clear();
} }
} }
if (player.TilesCreated != null)
{
if (player.TilePlaceThreshold >= Config.TilePlaceThreshold)
{
TSPlayer.Server.RevertTiles(player.TilesCreated);
}
if (player.TilePlaceThreshold > 0)
{
player.TilePlaceThreshold = 0;
player.TilesCreated.Clear();
}
}
if (player.ForceSpawn && (DateTime.Now - player.LastDeath).Seconds >= 3) if (player.ForceSpawn && (DateTime.Now - player.LastDeath).Seconds >= 3)
{ {
player.Spawn(); player.Spawn();
@ -679,24 +691,16 @@ namespace TShockAPI
return; return;
} }
// Stop accepting updates from player as this player is going to be kicked/banned during OnUpdate (different thread so can produce race conditions) using (var data = new MemoryStream(e.Msg.readBuffer, e.Index, e.Length))
if (player.TileThreshold >= Config.TileThreshold && !player.Group.HasPermission(Permissions.ignorekilltiledetection))
{ {
e.Handled = true; try
}
else
{
using (var data = new MemoryStream(e.Msg.readBuffer, e.Index, e.Length))
{ {
try if (GetDataHandlers.HandlerGetData(type, player, data))
{ e.Handled = true;
if (GetDataHandlers.HandlerGetData(type, player, data)) }
e.Handled = true; catch (Exception ex)
} {
catch (Exception ex) Log.Error(ex.ToString());
{
Log.Error(ex.ToString());
}
} }
} }
} }
@ -972,6 +976,16 @@ namespace TShockAPI
public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY) public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY)
{ {
if (player.TileKillThreshold >= Config.TileKillThreshold && !player.Group.HasPermission(Permissions.ignorekilltiledetection))
{
player.LastThreat = DateTime.UtcNow;
return true;
}
if (player.TilePlaceThreshold >= Config.TilePlaceThreshold && !player.Group.HasPermission(Permissions.ignoreplacetiledetection))
{
player.LastThreat = DateTime.UtcNow;
return true;
}
if (!player.Group.HasPermission(Permissions.canbuild)) if (!player.Group.HasPermission(Permissions.canbuild))
{ {
player.SendMessage("You do not have permission to build!", Color.Red); player.SendMessage("You do not have permission to build!", Color.Red);