Merge pull request #1642 from AxeelAnder/npc-buff-bouncer

Add cheat detection on NPCAddBuff
This commit is contained in:
Ziteng Wang 2018-10-20 22:02:19 -07:00 committed by GitHub
commit e14af631e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 139 additions and 0 deletions

View file

@ -90,6 +90,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* Added filtering and validation on packet 96 (Teleport player through portal) (@QuiCM)
* Update tracker now uses TLS (@pandabear41)
* When deleting an user account, any player logged in to that account is now logged out properly (@Enerdy)
* Add NPCAddBuff data handler and bouncer (@AxeelAnder)
## TShock 4.3.25
* Fixed a critical exploit in the Terraria protocol that could cause massive unpreventable world corruption as well as a number of other problems. Thanks to @bartico6 for reporting. Fixed by the efforts of @QuiCM, @hakusaro, and tips in the right directioon from @bartico6.

View file

@ -36,6 +36,31 @@ namespace TShockAPI
/// <summary>Bouncer is the TShock anti-hack and anti-cheat system.</summary>
internal sealed class Bouncer
{
static Dictionary<byte, short> NPCAddBuffTimeMax = new Dictionary<byte, short>()
{
{ BuffID.Poisoned, 3600 },
{ BuffID.OnFire, 1200 },
{ BuffID.CursedInferno, 420 },
{ BuffID.Frostburn, 900 },
{ BuffID.Ichor, 1200 },
{ BuffID.Venom, 1260 },
{ BuffID.Midas, 120 },
{ BuffID.Wet, 1500 },
{ BuffID.Slimed, 1500 },
{ BuffID.Lovestruck, 1800 },
{ BuffID.Stinky, 1800 },
{ BuffID.SoulDrain, 30 },
{ BuffID.ShadowFlame, 660 },
{ BuffID.DryadsWard, 120 },
{ BuffID.BoneJavelin, 900 },
{ BuffID.StardustMinionBleed, 900 },
{ BuffID.DryadsWardDebuff, 120 },
{ BuffID.Daybreak, 300 },
{ BuffID.BetsysCurse, 600 },
{ BuffID.Oiled, 540 }
};
/// <summary>Constructor call initializes Bouncer and related functionality.</summary>
/// <returns>A new Bouncer.</returns>
internal Bouncer()
@ -49,6 +74,7 @@ namespace TShockAPI
GetDataHandlers.PlayerAnimation += OnPlayerAnimation;
GetDataHandlers.NPCStrike += OnNPCStrike;
GetDataHandlers.ItemDrop += OnItemDrop;
GetDataHandlers.NPCAddBuff += OnNPCAddBuff;
GetDataHandlers.PlayerBuff += OnPlayerBuff;
GetDataHandlers.ChestItemChange += OnChestItemChange;
GetDataHandlers.NPCHome += OnUpdateNPCHome;
@ -454,6 +480,65 @@ namespace TShockAPI
}
}
/// <summary>Handles NPCAddBuff events.</summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>
internal void OnNPCAddBuff(object sender, GetDataHandlers.NPCAddBuffEventArgs args)
{
short id = args.ID;
byte type = args.Type;
short time = args.Time;
if (id >= Main.npc.Length)
{
args.Handled = true;
return;
}
NPC npc = Main.npc[id];
if (npc == null)
{
args.Handled = true;
return;
}
if (args.Player.IsBeingDisabled())
{
args.Handled = true;
return;
}
bool detectedNPCBuffTimeCheat = false;
if (NPCAddBuffTimeMax.ContainsKey(type))
{
if (time > NPCAddBuffTimeMax[type])
{
detectedNPCBuffTimeCheat = true;
}
if (npc.townNPC && npc.netID != NPCID.Guide && npc.netID != NPCID.Clothier)
{
if (type != BuffID.Lovestruck && type != BuffID.Stinky && type != BuffID.DryadsWard &&
type != BuffID.Wet && type != BuffID.Slimed)
{
detectedNPCBuffTimeCheat = true;
}
}
}
else
{
detectedNPCBuffTimeCheat = true;
}
if (detectedNPCBuffTimeCheat)
{
args.Player.Kick("Added buff to NPC abnormally.", true);
args.Handled = true;
}
}
/// <summary>Handles Buff events.</summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>

View file

@ -1003,6 +1003,46 @@ namespace TShockAPI
NPCHome.Invoke(null, args);
return args.Handled;
}
/// <summary>
/// For use in a NPCAddBuff event
/// </summary>
public class NPCAddBuffEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// The ID of the npc
/// </summary>
public short ID { get; set; }
/// <summary>
/// Buff Type
/// </summary>
public byte Type { get; set; }
/// <summary>
/// Time the buff lasts
/// </summary>
public short Time { get; set; }
}
/// <summary>
/// NPCAddBuff - Called when a npc is buffed
/// </summary>
public static HandlerList<NPCAddBuffEventArgs> NPCAddBuff = new HandlerList<NPCAddBuffEventArgs>();
private static bool OnNPCAddBuff(TSPlayer player, MemoryStream data, short id, byte type, short time)
{
if (NPCAddBuff == null)
return false;
var args = new NPCAddBuffEventArgs
{
Player = player,
Data = data,
ID = id,
Type = type,
Time = time
};
NPCAddBuff.Invoke(null, args);
return args.Handled;
}
/// <summary>
/// For use in a PlayerBuff event
@ -1455,6 +1495,7 @@ namespace TShockAPI
{ PacketTypes.PlayerSlot, HandlePlayerSlot },
{ PacketTypes.TileGetSection, HandleGetSection },
{ PacketTypes.UpdateNPCHome, UpdateNPCHome },
{ PacketTypes.NpcAddBuff, HandleNPCAddBuff },
{ PacketTypes.PlayerAddBuff, HandlePlayerAddBuff },
{ PacketTypes.ItemDrop, HandleItemDrop },
{ PacketTypes.UpdateItemDrop, HandleItemDrop },
@ -2627,6 +2668,18 @@ namespace TShockAPI
}
return false;
}
private static bool HandleNPCAddBuff(GetDataHandlerArgs args)
{
var id = args.Data.ReadInt16();
var type = args.Data.ReadInt8();
var time = args.Data.ReadInt16();
if (OnNPCAddBuff(args.Player, args.Data, id, type, time))
return true;
return false;
}
private static bool HandlePlayerAddBuff(GetDataHandlerArgs args)
{