From e53b723bd89b8e0d16e07f899908e5d5ae82f4ff Mon Sep 17 00:00:00 2001 From: punchready <22683812+punchready@users.noreply.github.com> Date: Wed, 19 Oct 2022 04:43:27 +0200 Subject: [PATCH 1/4] Fix grass mowing keeping hanging vines intact Creating a long row of grass with vines below and then mowing it without breaking the vines below could cause a tile framing stack overflow due to all vines being cleared at once if one of them is being broken on the server or if the client simply loads the corresponding section. Warning: this does not fix eventual existing worlds that are already in such a state. --- TShockAPI/Handlers/SendTileRectHandler.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TShockAPI/Handlers/SendTileRectHandler.cs b/TShockAPI/Handlers/SendTileRectHandler.cs index c68895ae..883eff51 100644 --- a/TShockAPI/Handlers/SendTileRectHandler.cs +++ b/TShockAPI/Handlers/SendTileRectHandler.cs @@ -350,9 +350,13 @@ namespace TShockAPI.Handlers )) { UpdateServerTileState(tile, newTile, TileDataType.Tile); + if (TileID.Sets.IsVine[Main.tile[realX, realY + 1].type]) // vanilla does in theory break the vines on its own, but we can't trust that + { + WorldGen.KillTile(realX, realY + 1); + } } - // Conversion: only sends a 1x1 rect + // Conversion: only sends a 1x1 rect; has to happen AFTER grass mowing as it would otherwise also let mowing through, but without fixing vines if (rectWidth == 1 && rectLength == 1) { ProcessConversionSpreads(tile, newTile); From 9e4bf72cbf2a457b3c86422b9708cedd4ebdfdf0 Mon Sep 17 00:00:00 2001 From: punchready <22683812+punchready@users.noreply.github.com> Date: Wed, 19 Oct 2022 04:51:47 +0200 Subject: [PATCH 2/4] Update changelog --- docs/changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.md b/docs/changelog.md index 703f35a2..653bd529 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -58,6 +58,7 @@ Use past tense when adding new entries; sign your name off when you add or chang * Introduce `AddPlayerBuffWhitelist` (replacing `WhitelistBuffMaxTime`), which allows us to specify the maximum amount of ticks a buff can be applied for, and if it can be applied without the target being in PvP. * When rejecting from `OnPlayerBuff`, instead of sending a `PlayerAddBuff` packet with the rejected buff (essentially a no-op, as the sender implicitly applies the buff to the target, and causes desync as the buff was rejected), send a `PlayerBuff` to re-sync the target's buffs, without the buff we just rejected. * Added new tile provider. Use `-constileation` or `-c` to use it. Constileation is an alternative tile provider to Tiled and HeapTile. (@SignatureBeef) +* Fixed an exploit with grass mowing not removing hanging vines. (@punchready) ## TShock 4.5.18 * Fixed `TSPlayer.GiveItem` not working if the player is in lava. (@PotatoCider) From 4e542d6ef68c5bb18d0e67c048fd86f17c9c3253 Mon Sep 17 00:00:00 2001 From: punchready <22683812+punchready@users.noreply.github.com> Date: Wed, 19 Oct 2022 05:20:18 +0200 Subject: [PATCH 3/4] Skip tile rect changes close to the world edge --- TShockAPI/Handlers/SendTileRectHandler.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TShockAPI/Handlers/SendTileRectHandler.cs b/TShockAPI/Handlers/SendTileRectHandler.cs index 883eff51..607cba03 100644 --- a/TShockAPI/Handlers/SendTileRectHandler.cs +++ b/TShockAPI/Handlers/SendTileRectHandler.cs @@ -157,8 +157,9 @@ namespace TShockAPI.Handlers int realY = tileY + y; // Do not process tiles outside of the world boundaries - if ((realX < 0 || realX >= Main.maxTilesX) - || (realY < 0 || realY > Main.maxTilesY)) + // The hidden world strip is 40 tiles wide/tall, use 10 instead just to be safe to avoid off-by-one errors + if ((realX < 10 || realX >= Main.maxTilesX - 10) + || (realY < 10 || realY > Main.maxTilesY - 10)) { processed[x, y] = true; continue; From 25500bcccc6ee031295d1a219b28e236341bb293 Mon Sep 17 00:00:00 2001 From: punchready <22683812+punchready@users.noreply.github.com> Date: Wed, 19 Oct 2022 05:26:07 +0200 Subject: [PATCH 4/4] Use ad hoc checks for world boundary instead --- TShockAPI/Handlers/SendTileRectHandler.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/TShockAPI/Handlers/SendTileRectHandler.cs b/TShockAPI/Handlers/SendTileRectHandler.cs index 607cba03..7fcbf2c8 100644 --- a/TShockAPI/Handlers/SendTileRectHandler.cs +++ b/TShockAPI/Handlers/SendTileRectHandler.cs @@ -157,9 +157,8 @@ namespace TShockAPI.Handlers int realY = tileY + y; // Do not process tiles outside of the world boundaries - // The hidden world strip is 40 tiles wide/tall, use 10 instead just to be safe to avoid off-by-one errors - if ((realX < 10 || realX >= Main.maxTilesX - 10) - || (realY < 10 || realY > Main.maxTilesY - 10)) + if ((realX < 0 || realX >= Main.maxTilesX) + || (realY < 0 || realY > Main.maxTilesY)) { processed[x, y] = true; continue; @@ -351,7 +350,7 @@ namespace TShockAPI.Handlers )) { UpdateServerTileState(tile, newTile, TileDataType.Tile); - if (TileID.Sets.IsVine[Main.tile[realX, realY + 1].type]) // vanilla does in theory break the vines on its own, but we can't trust that + if (WorldGen.InWorld(realX, realY + 1) && TileID.Sets.IsVine[Main.tile[realX, realY + 1].type]) // vanilla does in theory break the vines on its own, but we can't trust that { WorldGen.KillTile(realX, realY + 1); }