From 1d9bc7d1aff6afe3b0c26ab43acb31a3f3c5960c Mon Sep 17 00:00:00 2001 From: James Puleo Date: Wed, 27 Apr 2022 21:01:20 -0400 Subject: [PATCH] Fixed Bouncer possibly rejecting Explosive Bunny critter releases When using a Bunny Cannon, an Explosive Bunny item (which is also a critter release item) is used to create an Explosive Bunny projectile, which will later (in the future) release an Explosive Bunny NPC, by the release critter packet. The existing checks required that the player be actively selecting the item to create the critter, however this didn't make sense for Explosive Bunnies, as they would be released in the future, possibly when the player was no longer selecting that item. This commit relaxes the restrictions on Explosive Bunny critter releases, now requiring either holding the release item, or having recently created an Explosive Bunny projectile, and that the release coordinates are within the area of one of their Explosive Bunny projectiles. --- CHANGELOG.md | 1 + TShockAPI/Bouncer.cs | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3dfed3..c1ca3a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Fixed `TSPlayer.GiveItem` not working if the player is in lava. (@gohjoseph) * Only allow using Teleportation Potions, Magic Conch, and Demon Conch whilst holding them. (@drunderscore) * Updated server startup language to be more clear when encountering a fatal startup error. Now, the server gives more context as to what happened so that there's a better chance of people being able to help themselves. (@hakusaro) +* Fixed Bouncer rejecting Explosive Bunny critter release when using the Bunny Cannon, if the player had since stopped selecting the Explosive Bunny. (@drunderscore) ## TShock 4.5.17 * Fixed duplicate characters (twins) after repeatedly logging in as the same character due to connection not being immediately closed during `NetHooks_NameCollision`. (@gohjoseph) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index dae66461..e9ed119f 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1858,14 +1858,48 @@ namespace TShockAPI return; } - // if released npc not from its item (from crafted packet) - // e.g. using bunny item to release golden bunny - if (args.Player.TPlayer.lastVisualizedSelectedItem.makeNPC != type && args.Player.TPlayer.lastVisualizedSelectedItem.placeStyle != style) + void rejectForCritterNotReleasedFromItem() { TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC released different critter from {0}", args.Player.Name); args.Player.Kick("Released critter was not from its item.", true); args.Handled = true; - return; + } + + // if released npc not from its item (from crafted packet) + // e.g. using bunny item to release golden bunny + if (args.Player.TPlayer.lastVisualizedSelectedItem.makeNPC != type || args.Player.TPlayer.lastVisualizedSelectedItem.placeStyle != style) + { + // If the critter is an Explosive Bunny, check if we've recently created an Explosive Bunny projectile. + // If we have, check if the critter we are trying to create is within range of the projectile + // If we have at least one of those, then this wasn't a crafted packet, but simply a delayed critter release from an + // Explosive Bunny projectile. + if (type == NPCID.ExplosiveBunny) + { + bool areAnyBunnyProjectilesInRange; + + lock (args.Player.RecentlyCreatedProjectiles) + { + areAnyBunnyProjectilesInRange = args.Player.RecentlyCreatedProjectiles.Any(projectile => + { + if (projectile.Type != ProjectileID.ExplosiveBunny) + return false; + + var projectileInstance = Main.projectile[projectile.Index]; + return projectileInstance.active && projectileInstance.WithinRange(new Vector2(args.X, args.Y), 32.0f); + }); + } + + if (!areAnyBunnyProjectilesInRange) + { + rejectForCritterNotReleasedFromItem(); + return; + } + } + else + { + rejectForCritterNotReleasedFromItem(); + return; + } } if (args.Player.IsBouncerThrottled())