diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 7287924f..bb9937a6 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -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,40 @@ namespace TShockAPI return; } + /// Handles PlayerZone events for preventing spawning NPC maliciously. + /// The object that triggered the event. + /// The packet arguments that the event has. + internal void OnPlayerZone(object sender, GetDataHandlers.PlayerZoneEventArgs args) + { + bool hasSolarTower = false; + bool hasVortexTower = false; + bool hasNebulaTower = false; + bool hasStardustTower = false; + + // May need to optimize + 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; + } + } + /// Bouncer's KillMe hook stops crash exploits from out of bounds values. /// The object that triggered the event. /// The packet arguments that the event has. diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index a7792569..dd18e502 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -550,6 +550,56 @@ namespace TShockAPI return args.Handled; } + /// + /// For use in a PlayerZone event + /// + public class PlayerZoneEventArgs : GetDataHandledEventArgs + { + /// + /// The Terraria playerID of the player + /// + public byte PlayerId { get; set; } + /// + /// 0 = Dungeon, 1 = Corruption,2 =Holy, 3 = Meteor, 4 = Jungle, 5 = Snow, 6 = Crimson, 7 = Water Candle + /// + public BitsByte Zone1 { get; set; } + /// + /// 0 = Peace Candle, 1 = Solar Tower, 2 = Vortex Tower, 3 = Nebula Tower, 4 = Stardust Tower, 5 = Desert, 6 = Glowshroom, 7 = Underground Desert + /// + public BitsByte Zone2 { get; set; } + /// + /// 0 = Overworld, 1 = Dirt Layer, 2 = Rock Layer, 3 = Underworld, 4 = Beach, 5 = Rain, 6 = Sandstorm + /// + public BitsByte Zone3 { get; set; } + /// + /// 0 = Old One's Army + /// + public BitsByte Zone4 { get; set; } + } + /// + /// PlayerZone - When the player sends it's zone/biome information to the server + /// + public static HandlerList PlayerZone = new HandlerList(); + + 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; + } + /// The event args object for the HealOtherPlayer event 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();