Merge pull request #1644 from AxeelAnder/player-zone

Added PlayerZone handler and bouncer, detect lunar towers cheat
This commit is contained in:
Ziteng Wang 2018-10-25 22:58:43 -07:00 committed by GitHub
commit 0d3abc512a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 0 deletions

View file

@ -92,6 +92,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* 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)
* Improved config file documentation (@Enerdy)
* Add PlayerZone 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

@ -83,6 +83,7 @@ namespace TShockAPI
GetDataHandlers.LiquidSet += OnLiquidSet;
GetDataHandlers.ProjectileKill += OnProjectileKill;
GetDataHandlers.PlayerUpdate += OnPlayerUpdate;
GetDataHandlers.PlayerZone += OnPlayerZone;
GetDataHandlers.KillMe += OnKillMe;
GetDataHandlers.NewProjectile += OnNewProjectile;
GetDataHandlers.PlaceObject += OnPlaceObject;
@ -1000,6 +1001,42 @@ namespace TShockAPI
return;
}
/// <summary>Handles PlayerZone events for preventing spawning NPC maliciously.</summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>
internal void OnPlayerZone(object sender, GetDataHandlers.PlayerZoneEventArgs args)
{
if(args.Zone2[1] || args.Zone2[2] || args.Zone2[3] || args.Zone2[4])
{
bool hasSolarTower = false;
bool hasVortexTower = false;
bool hasNebulaTower = false;
bool hasStardustTower = false;
foreach (var npc in Main.npc)
{
if (npc.netID == NPCID.LunarTowerSolar)
hasSolarTower = true;
else if (npc.netID == NPCID.LunarTowerVortex)
hasVortexTower = true;
else if (npc.netID == NPCID.LunarTowerNebula)
hasNebulaTower = true;
else if (npc.netID == NPCID.LunarTowerStardust)
hasStardustTower = true;
}
if ((args.Zone2[1] && !hasSolarTower)
|| (args.Zone2[2] && !hasVortexTower)
|| (args.Zone2[3] && !hasNebulaTower)
|| (args.Zone2[4] && !hasStardustTower)
)
{
args.Handled = true;
return;
}
}
}
/// <summary>Bouncer's KillMe hook stops crash exploits from out of bounds values.</summary>
/// <param name="sender">The object that triggered the event.</param>
/// <param name="args">The packet arguments that the event has.</param>

View file

@ -550,6 +550,56 @@ namespace TShockAPI
return args.Handled;
}
/// <summary>
/// For use in a PlayerZone event
/// </summary>
public class PlayerZoneEventArgs : GetDataHandledEventArgs
{
/// <summary>
/// The Terraria playerID of the player
/// </summary>
public byte PlayerId { get; set; }
/// <summary>
/// 0 = Dungeon, 1 = Corruption,2 =Holy, 3 = Meteor, 4 = Jungle, 5 = Snow, 6 = Crimson, 7 = Water Candle
/// </summary>
public BitsByte Zone1 { get; set; }
/// <summary>
/// 0 = Peace Candle, 1 = Solar Tower, 2 = Vortex Tower, 3 = Nebula Tower, 4 = Stardust Tower, 5 = Desert, 6 = Glowshroom, 7 = Underground Desert
/// </summary>
public BitsByte Zone2 { get; set; }
/// <summary>
/// 0 = Overworld, 1 = Dirt Layer, 2 = Rock Layer, 3 = Underworld, 4 = Beach, 5 = Rain, 6 = Sandstorm
/// </summary>
public BitsByte Zone3 { get; set; }
/// <summary>
/// 0 = Old One's Army
/// </summary>
public BitsByte Zone4 { get; set; }
}
/// <summary>
/// PlayerZone - When the player sends it's zone/biome information to the server
/// </summary>
public static HandlerList<PlayerZoneEventArgs> PlayerZone = new HandlerList<PlayerZoneEventArgs>();
private static bool OnPlayerZone(TSPlayer player, MemoryStream data, byte plr, BitsByte zone1, BitsByte zone2, BitsByte zone3, BitsByte zone4)
{
if (PlayerZone == null)
return false;
var args = new PlayerZoneEventArgs
{
Player = player,
Data = data,
PlayerId = plr,
Zone1 = zone1,
Zone2 = zone2,
Zone3 = zone3,
Zone4 = zone4
};
PlayerZone.Invoke(null, args);
return args.Handled;
}
/// <summary>The event args object for the HealOtherPlayer event</summary>
public class HealOtherPlayerEventArgs : GetDataHandledEventArgs
{
@ -1479,6 +1529,7 @@ namespace TShockAPI
{
{ PacketTypes.PlayerInfo, HandlePlayerInfo },
{ PacketTypes.PlayerUpdate, HandlePlayerUpdate },
{ PacketTypes.Zones, HandlePlayerZone },
{ PacketTypes.Tile, HandleTile },
{ PacketTypes.PlaceObject, HandlePlaceObject },
{ PacketTypes.TileSendSquare, HandleSendTileSquare },
@ -2402,6 +2453,25 @@ namespace TShockAPI
return true;
}
private static bool HandlePlayerZone(GetDataHandlerArgs args)
{
if (args.Player == null || args.TPlayer == null || args.Data == null)
{
return true;
}
var plr = args.Data.ReadInt8();
BitsByte zone1 = args.Data.ReadInt8();
BitsByte zone2 = args.Data.ReadInt8();
BitsByte zone3 = args.Data.ReadInt8();
BitsByte zone4 = args.Data.ReadInt8();
if (OnPlayerZone(args.Player, args.Data, plr, zone1, zone2, zone3, zone4))
return true;
return false;
}
private static bool HandleProjectileNew(GetDataHandlerArgs args)
{
short ident = args.Data.ReadInt16();