Merge branch 'general-devel' into fix-infinities

This commit is contained in:
Lucas Nicodemus 2025-03-10 00:16:22 +09:00 committed by GitHub
commit 25644449e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 31 deletions

View file

@ -95,6 +95,7 @@ namespace TShockAPI
{ PacketTypes.TileSendSquare, HandleSendTileRect },
{ PacketTypes.ItemDrop, HandleItemDrop },
{ PacketTypes.ItemOwner, HandleItemOwner },
{ PacketTypes.NpcItemStrike, HandleNpcItemStrike },
{ PacketTypes.ProjectileNew, HandleProjectileNew },
{ PacketTypes.NpcStrike, HandleNpcStrike },
{ PacketTypes.ProjectileDestroy, HandleProjectileKill },
@ -2945,6 +2946,13 @@ namespace TShockAPI
return false;
}
private static bool HandleNpcItemStrike(GetDataHandlerArgs args)
{
// Never sent by vanilla client, ignore this
TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandleNpcItemStrike surprise packet! Someone tell the TShock team! {0}", args.Player.Name));
return true;
}
private static bool HandleProjectileNew(GetDataHandlerArgs args)
{
short ident = args.Data.ReadInt16();

View file

@ -78,6 +78,13 @@ namespace TShockAPI.Handlers
Removal,
}
public enum MatchResult
{
NotMatched,
RejectChanges,
BroadcastChanges,
}
private readonly int Width;
private readonly int Height;
@ -179,11 +186,11 @@ namespace TShockAPI.Handlers
/// <param name="player">The player the operation originates from.</param>
/// <param name="rect">The tile rectangle of the operation.</param>
/// <returns><see langword="true"/>, if the rect matches this operation and the changes have been applied, otherwise <see langword="false"/>.</returns>
public bool Matches(TSPlayer player, TileRect rect)
public MatchResult Matches(TSPlayer player, TileRect rect)
{
if (rect.Width != Width || rect.Height != Height)
{
return false;
return MatchResult.NotMatched;
}
for (int x = 0; x < rect.Width; x++)
@ -195,7 +202,7 @@ namespace TShockAPI.Handlers
{
if (tile.Type != TileType)
{
return false;
return MatchResult.NotMatched;
}
}
if (Type is MatchType.Placement or MatchType.StateChange)
@ -204,7 +211,7 @@ namespace TShockAPI.Handlers
{
if (tile.FrameX < 0 || tile.FrameX > MaxFrameX || tile.FrameX % FrameXStep != 0)
{
return false;
return MatchResult.NotMatched;
}
}
if (MaxFrameY != IGNORE_FRAME)
@ -214,7 +221,7 @@ namespace TShockAPI.Handlers
// this is the only tile type sent in a tile rect where the frame have a different pattern (56, 74, 92 instead of 54, 72, 90)
if (!(TileType == TileID.LunarMonolith && tile.FrameY % FrameYStep == 2))
{
return false;
return MatchResult.NotMatched;
}
}
}
@ -223,7 +230,7 @@ namespace TShockAPI.Handlers
{
if (tile.Active)
{
return false;
return MatchResult.NotMatched;
}
}
}
@ -236,7 +243,7 @@ namespace TShockAPI.Handlers
if (!player.HasBuildPermission(x, y))
{
// for simplicity, let's pretend that the edit was valid, but do not execute it
return true;
return MatchResult.RejectChanges;
}
}
}
@ -257,10 +264,10 @@ namespace TShockAPI.Handlers
}
}
return false;
return MatchResult.NotMatched;
}
private bool MatchPlacement(TSPlayer player, TileRect rect)
private MatchResult MatchPlacement(TSPlayer player, TileRect rect)
{
for (int x = rect.X; x < rect.Y + rect.Width; x++)
{
@ -268,7 +275,7 @@ namespace TShockAPI.Handlers
{
if (Main.tile[x, y].active()) // the client will kill tiles that auto break before placing the object
{
return false;
return MatchResult.NotMatched;
}
}
}
@ -277,7 +284,7 @@ namespace TShockAPI.Handlers
if (TShock.TileBans.TileIsBanned((short)TileType, player))
{
// for simplicity, let's pretend that the edit was valid, but do not execute it
return true;
return MatchResult.RejectChanges;
}
for (int x = 0; x < rect.Width; x++)
@ -291,10 +298,10 @@ namespace TShockAPI.Handlers
}
}
return true;
return MatchResult.BroadcastChanges;
}
private bool MatchStateChange(TSPlayer player, TileRect rect)
private MatchResult MatchStateChange(TSPlayer player, TileRect rect)
{
for (int x = rect.X; x < rect.Y + rect.Width; x++)
{
@ -302,7 +309,7 @@ namespace TShockAPI.Handlers
{
if (!Main.tile[x, y].active() || Main.tile[x, y].type != TileType)
{
return false;
return MatchResult.NotMatched;
}
}
}
@ -322,18 +329,18 @@ namespace TShockAPI.Handlers
}
}
return true;
return MatchResult.BroadcastChanges;
}
private bool MatchRemoval(TSPlayer player, TileRect rect)
private MatchResult MatchRemoval(TSPlayer player, TileRect rect)
{
for (int x = rect.X; x < rect.Y + rect.Width; x++)
for (int x = rect.X; x < rect.X + rect.Width; x++)
{
for (int y = rect.Y; y < rect.Y + rect.Height; y++)
{
if (!Main.tile[x, y].active() || Main.tile[x, y].type != TileType)
{
return false;
return MatchResult.NotMatched;
}
}
}
@ -348,7 +355,7 @@ namespace TShockAPI.Handlers
}
}
return true;
return MatchResult.BroadcastChanges;
}
}
@ -364,7 +371,7 @@ namespace TShockAPI.Handlers
TileRectMatch.Placement(2, 3, TileID.TargetDummy, 54, 36, 18, 18),
TileRectMatch.Placement(3, 4, TileID.TeleportationPylon, 468, 54, 18, 18),
TileRectMatch.Placement(2, 3, TileID.DisplayDoll, 126, 36, 18, 18),
TileRectMatch.Placement(2, 3, TileID.HatRack, 90, 54, 18, 18),
TileRectMatch.Placement(3, 4, TileID.HatRack, 90, 54, 18, 18),
TileRectMatch.Placement(2, 2, TileID.ItemFrame, 162, 18, 18, 18),
TileRectMatch.Placement(3, 3, TileID.WeaponsRack2, 90, 36, 18, 18),
TileRectMatch.Placement(1, 1, TileID.FoodPlatter, 18, 0, 18, 18),
@ -436,7 +443,7 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect rejected from throttle from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
@ -446,7 +453,7 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect rejected from being disabled from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
@ -468,7 +475,7 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect reimplemented from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
@ -478,7 +485,7 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect rejected from out of range from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
@ -488,19 +495,23 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect reimplemented from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
// check if the rect matches any valid operation
foreach (TileRectMatch match in Matches)
{
if (match.Matches(args.Player, rect))
var result = match.Matches(args.Player, rect);
if (result != TileRectMatch.MatchResult.NotMatched)
{
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect reimplemented from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
if (result == TileRectMatch.MatchResult.RejectChanges)
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
if (result == TileRectMatch.MatchResult.BroadcastChanges)
TSPlayer.All.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
}
@ -511,14 +522,14 @@ namespace TShockAPI.Handlers
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect reimplemented from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}
TShock.Log.ConsoleDebug(GetString($"Bouncer / SendTileRect rejected from matches from {args.Player.Name}"));
// send correcting data
args.Player.SendTileRect(args.TileX, args.TileY, args.Length, args.Width);
args.Player.SendTileRect(args.TileX, args.TileY, args.Width, args.Length);
return;
}

View file

@ -96,6 +96,11 @@ Use past tense when adding new entries; sign your name off when you add or chang
* * Detected invalid installations, by checking for a file named `TerrariaServer.exe`. (@drunderscore)
* This made the two most common installation mistakes (extracting into the Terraria client directory, and extracting TShock 5 or newer into a TShock 4 or older install) prompt the user with a more useful diagnostic, rather than (likely) crashing moments later.
* Changed Bouncer to block updates which set the following fields to infinity or NaN: player position, projectile position, projectile velocity, item position, and item velocity. (@Arthri)
* Updated `TShockAPI.Handlers.SendTileRectHandler` (@LaoSparrow):
* Fixed incorrect validating range in `TileRectMatch.MatchRemoval`.
* Fixed tile rect changes (e.g. turning on and off campfires) are not synced between clients.
* Fixed unable to place Hat Rack without permission `tshock.ignore.sendtilesquare`.
* Updated `GetDataHandlers` to ignore `NpcItemStrike(msgid 24)`, which should never be sent by a vanilla client. (@LaoSparrow)
## TShock 5.2.1
* Updated `TSPlayer.GodMode`. (@AgaSpace)