From acb6a96245609c90546d5ecb5da7192562df23c2 Mon Sep 17 00:00:00 2001 From: shell627 <69633838+Terrarxxn@users.noreply.github.com> Date: Wed, 1 Dec 2021 00:18:02 +0600 Subject: [PATCH 1/4] Fix item dupe via /logout & NPC (#2495 issue) --- CHANGELOG.md | 1 + TShockAPI/Commands.cs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a73f8c..43c4b274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin ## TShock 4.5.12 * Fixed the ability to spawn Zenith projectile with non-original items. (@AgaSpace) +* Fixed item dupe via /logout & NPC. (@Terrarxxn) ## TShock 4.5.11 * Add the new allowed buff TentacleSpike to NPC buff cheat detection bouncer. (@sgkoishi) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 71e10a9d..09d4b253 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -911,6 +911,12 @@ namespace TShockAPI return; } + if (args.Player.TPlayer.talkNPC != -1) + { + args.Player.SendErrorMessage("Please close NPC window for logging out."); + return; + } + args.Player.Logout(); args.Player.SendSuccessMessage("You have been successfully logged out of your account."); if (Main.ServerSideCharacter) From e9b86b8f624b68fd6737dd0b17f98832f5ccbbda Mon Sep 17 00:00:00 2001 From: James Puleo Date: Fri, 16 Jul 2021 02:09:36 -0400 Subject: [PATCH 2/4] Improved the `/grow` command to reduce code duplication, use `TileID` constants for less ambiguous types. --- CHANGELOG.md | 3 + TShockAPI/Commands.cs | 329 +++++++++++++----------------------------- 2 files changed, 104 insertions(+), 228 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7a1e596..9afbf709 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Do not forget to sign every line you change with your name. (@hakusaro) * If there is no section called "Upcoming changes" below this line, please add one with `## Upcoming changes` as the first line, and then a bulleted item directly after with the first change. +## Upcoming changes +* Improved the `/grow` command to reduce code duplication, use `TileID` constants for less ambiguous types. (@drunderscore) + ## TShock 4.5.12 * Fixed the ability to spawn Zenith projectile with non-original items. (@AgaSpace) * Added hook `GetDataHandlers.OnNpcTalk` for NpcTalk and a handler for it that stops unregistered and logged out players from interacting with NPCs, preventing them from smuggling or duplicating items via NPC item slots. (@tru321) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 71e10a9d..57e99513 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -6301,7 +6301,7 @@ namespace TShockAPI public static void Grow(CommandArgs args) { - bool growevilAmb = args.Player.HasPermission(Permissions.growevil); + bool canGrowEvil = args.Player.HasPermission(Permissions.growevil); string subcmd = args.Parameters.Count == 0 ? "help" : args.Parameters[0].ToLower(); var name = "Fail"; @@ -6343,284 +6343,163 @@ namespace TShockAPI } break; - case "basic": - for (int i = x - 2; i < x + 3; i++) + bool rejectCannotGrowEvil() { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 2; - Main.tile[i, y].wall = 0; + if(!canGrowEvil) + { + args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + return false; + } + + return true; } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Basic Tree"; + + bool prepareAreaForGrow(ushort groundType = TileID.Grass, bool evil = false) + { + if(evil && !rejectCannotGrowEvil()) + return false; + + for (var i = x - 2; i < x + 3; i++) + { + Main.tile[i, y].active(true); + Main.tile[i, y].type = groundType; + Main.tile[i, y].wall = WallID.None; + } + Main.tile[x, y - 1].wall = WallID.None; + + return true; + } + + bool growTree(ushort groundType, string fancyName, bool evil = false) + { + if(!prepareAreaForGrow(groundType, evil)) + return false; + WorldGen.GrowTree(x, y); + name = fancyName; + + return true; + } + + bool growTreeByType(ushort groundType, string fancyName, ushort typeToPrepare = 2, bool evil = false) + { + if(!prepareAreaForGrow(typeToPrepare, evil)) + return false; + WorldGen.TryGrowingTreeByType(groundType, x, y); + name = fancyName; + + return true; + } + + bool growPalmTree(ushort sandType, ushort supportingType, string properName, bool evil = false) + { + if(evil && !rejectCannotGrowEvil()) + return false; + + for (int i = x - 2; i < x + 3; i++) + { + Main.tile[i, y].active(true); + Main.tile[i, y].type = sandType; + Main.tile[i, y].wall = WallID.None; + } + for (int i = x - 2; i < x + 3; i++) + { + Main.tile[i, y + 1].active(true); + Main.tile[i, y + 1].type = supportingType; + Main.tile[i, y + 1].wall = WallID.None; + } + + Main.tile[x, y - 1].wall = WallID.None; + WorldGen.GrowPalmTree(x, y); + + name = properName; + + return true; + } + + case "basic": + growTree(TileID.Grass, "Basic Tree"); break; case "boreal": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 147; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Boreal Tree"; + growTree(TileID.SnowBlock, "Boreal Tree"); break; case "mahogany": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 60; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Rich Mahogany"; + growTree(TileID.JungleGrass, "Rich Mahogany"); break; case "sakura": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 2; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(596, x, y); - name = "Sakura Tree"; + growTreeByType(TileID.VanityTreeSakura, "Sakura Tree"); break; case "willow": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 2; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(616, x, y); - name = "Willow Tree"; + growTreeByType(TileID.VanityTreeYellowWillow, "Willow Tree"); break; case "shadewood": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 199; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Shadewood tree"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growTree(TileID.CrimsonGrass, "Shadewood Tree", true)) + return; break; case "ebonwood": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 23; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Ebonwood Tree"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growTree(TileID.CorruptGrass, "Ebonwood Tree", true)) + return; break; case "pearlwood": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 109; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowTree(x, y); - name = "Pearlwood Tree"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growTree(TileID.HallowedGrass, "Pearlwood Tree", true)) + return; break; case "palm": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 53; - Main.tile[i, y].wall = 0; - } - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y + 1].active(true); - Main.tile[i, y + 1].type = 397; - Main.tile[i, y + 1].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowPalmTree(x, y); - name = "Desert Palm"; + growPalmTree(TileID.Sand, TileID.HardenedSand, "Desert Palm"); break; case "hallowpalm": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 116; - Main.tile[i, y].wall = 0; - } - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y + 1].active(true); - Main.tile[i, y + 1].type = 402; - Main.tile[i, y + 1].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowPalmTree(x, y); - name = "Hallow Palm"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growPalmTree(TileID.Pearlsand, TileID.HallowHardenedSand, "Hallow Palm", true)) + return; break; case "crimsonpalm": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 234; - Main.tile[i, y].wall = 0; - } - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y + 1].active(true); - Main.tile[i, y + 1].type = 399; - Main.tile[i, y + 1].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowPalmTree(x, y); - name = "Crimson Palm"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growPalmTree(TileID.Crimsand, TileID.CrimsonHardenedSand, "Crimson Palm", true)) + return; break; case "corruptpalm": - if (growevilAmb) - { - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 112; - Main.tile[i, y].wall = 0; - } - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y + 1].active(true); - Main.tile[i, y + 1].type = 398; - Main.tile[i, y + 1].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.GrowPalmTree(x, y); - name = "Corruption Palm"; - } - else args.Player.SendErrorMessage("You do not have permission to grow this tree type"); + if(!growPalmTree(TileID.Ebonsand, TileID.CorruptHardenedSand, "Corruption Palm", true)) + return; break; case "topaz": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(583, x, y); - name = "Topaz Gemtree"; + growTreeByType(TileID.TreeTopaz, "Topaz Gemtree", 1); break; case "amethyst": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(584, x, y); - name = "Amethyst Gemtree"; + growTreeByType(TileID.TreeAmethyst, "Amethyst Gemtree", 1); break; case "sapphire": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(585, x, y); - name = "Sapphire Gemtree"; + growTreeByType(TileID.TreeSapphire, "Sapphire Gemtree", 1); break; case "emerald": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(586, x, y); - name = "Emerald Gemtree"; + growTreeByType(TileID.TreeEmerald, "Emerald Gemtree", 1); break; case "ruby": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(587, x, y); - name = "Ruby Gemtree"; + growTreeByType(TileID.TreeRuby, "Ruby Gemtree", 1); break; case "diamond": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(588, x, y); - name = "Diamond Gemtree"; + growTreeByType(TileID.TreeDiamond, "Diamond Gemtree", 1); break; case "amber": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 1; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; - WorldGen.TryGrowingTreeByType(589, x, y); - name = "Amber Gemtree"; + growTreeByType(TileID.TreeAmber, "Amber Gemtree", 1); break; case "cactus": - Main.tile[x, y].type = 53; + Main.tile[x, y].type = TileID.Sand; WorldGen.GrowCactus(x, y); name = "Cactus"; break; @@ -6628,19 +6507,13 @@ namespace TShockAPI case "herb": Main.tile[x, y].active(true); Main.tile[x, y].frameX = 36; - Main.tile[x, y].type = 83; + Main.tile[x, y].type = TileID.MatureHerbs; WorldGen.GrowAlch(x, y); name = "Herb"; break; case "mushroom": - for (int i = x - 2; i < x + 3; i++) - { - Main.tile[i, y].active(true); - Main.tile[i, y].type = 70; - Main.tile[i, y].wall = 0; - } - Main.tile[x, y - 1].wall = 0; + prepareAreaForGrow(TileID.MushroomGrass); WorldGen.GrowShroom(x, y); name = "Glowing Mushroom Tree"; break; From 4aa75fe0235117c7dffd71da7ced9a62dfce5598 Mon Sep 17 00:00:00 2001 From: Chris <2648373+QuiCM@users.noreply.github.com> Date: Tue, 22 Feb 2022 19:15:58 +1030 Subject: [PATCH 3/4] Add suggestion Co-authored-by: Lucas Nicodemus --- TShockAPI/Commands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 09d4b253..fd065025 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -913,7 +913,7 @@ namespace TShockAPI if (args.Player.TPlayer.talkNPC != -1) { - args.Player.SendErrorMessage("Please close NPC window for logging out."); + args.Player.SendErrorMessage("Please close NPC windows before logging out."); return; } From 2f31322b5f8eb875f7f38f09412fd476e2641f03 Mon Sep 17 00:00:00 2001 From: Chris <2648373+QuiCM@users.noreply.github.com> Date: Wed, 23 Feb 2022 20:53:31 +1030 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93f4893e..6868d958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin ## Upcoming changes * Improved the `/grow` command to reduce code duplication, use `TileID` constants for less ambiguous types. (@drunderscore) +* Fixed item dupe via /logout & NPC. (@Terrarxxn) ## TShock 4.5.13 * Added hook `GetDataHandlers.OnReleaseNpc` to handling ReleaseNPC packet and a bouncer to stops unregistered and logged out players on SSC servers from releasing critters NPC. The bouncer has additional filter to stops players who tried to release different critter using crafted packet, e.g. using bunny item to release golden bunny. (@tru321) @@ -27,7 +28,6 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin ## TShock 4.5.12 * Fixed the ability to spawn Zenith projectile with non-original items. (@AgaSpace) -* Fixed item dupe via /logout & NPC. (@Terrarxxn) * Added hook `GetDataHandlers.OnNpcTalk` for NpcTalk and a handler for it that stops unregistered and logged out players from interacting with NPCs, preventing them from smuggling or duplicating items via NPC item slots. (@tru321) * Fixed the ability to create custom messages with your death (or the death of another player) (@AgaSpace) * Added the `OnSignRead` handler in `GetDataHandler`, and added the `SignRead` event. Added check to ensure the sign being read is within world bounds `(x >= 0 && y >= 0 && x < Main.maxTilesX && y < Main.maxTilesY)`. (@drunderscore)