diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b2e774..ddd198e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Added filter in `GetDataHandlers.HandleCatchNpc` that stops unregistered and logged out players on SSC servers to catch critters. (@tru321) * Fixed rejection check inside of `HandlePaintTile` to account for the Paint Sprayer (or Architect Gizmo Pack) being inside your inventory, rather than on an accessory slot. (@drunderscore) * Added the lanterns night event to the `/worldevent` command. (@0x3fcf1bbd) +* Marked `TSPlayer.SendTileSquare` as deprecated, and created `TSPlayer.SendTileSquareCentered` that sends a tile square centered around the passed coordinates. (@0x3fcf1bbd) +* Added coordinates clamping to `TSPlayer.SendTileRect` so as to avoid OOBs. (@0x3fcf1bbd) * Removed extraneous space causing build commands in README to fail. (@EtherTyper) ## TShock 4.5.12 diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 7f3894c1..dae66461 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -406,7 +406,7 @@ namespace TShockAPI ((action == EditAction.PlaceWall || action == EditAction.ReplaceWall) && editData >= Main.maxWallTypes)) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from editData out of bounds {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -421,7 +421,7 @@ namespace TShockAPI if (args.Player.Dead && TShock.Config.Settings.PreventDeadModification) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pdm) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -435,7 +435,7 @@ namespace TShockAPI if (TShock.TileBans.TileIsBanned(editData, args.Player)) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tb) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Player.SendErrorMessage("You do not have permission to place this tile."); args.Handled = true; return; @@ -458,7 +458,7 @@ namespace TShockAPI { TShock.Log.ConsoleError("Bouncer / OnTileEdit rejected from (placestyle) {0} {1} {2} placeStyle: {3} expectedStyle: {4}", args.Player.Name, action, editData, requestedPlaceStyle, actualItemPlaceStyle); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -469,7 +469,7 @@ namespace TShockAPI { TShock.Log.ConsoleError("Bouncer / OnTileEdit rejected from (placestyle) {0} {1} {2} placeStyle: {3} expectedStyle: {4}", args.Player.Name, action, editData, requestedPlaceStyle, correctedPlaceStyle); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -484,7 +484,7 @@ namespace TShockAPI if (Main.tileAxe[tile.type] && ((args.Player.TPlayer.mount.Type != 8 && selectedItem.axe == 0) && !ItemID.Sets.Explosives[selectedItem.netID] && args.Player.RecentFuse == 0)) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (axe) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -492,7 +492,7 @@ namespace TShockAPI else if (Main.tileHammer[tile.type] && ((args.Player.TPlayer.mount.Type != 8 && selectedItem.hammer == 0) && !ItemID.Sets.Explosives[selectedItem.netID] && args.Player.RecentFuse == 0)) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (hammer) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -503,7 +503,7 @@ namespace TShockAPI && !Main.tileAxe[tile.type] && !Main.tileHammer[tile.type] && tile.wall == 0 && args.Player.TPlayer.mount.Type != 8 && selectedItem.pick == 0 && selectedItem.type != ItemID.GravediggerShovel && !ItemID.Sets.Explosives[selectedItem.netID] && args.Player.RecentFuse == 0) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pick) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -514,7 +514,7 @@ namespace TShockAPI if (selectedItem.hammer == 0 && !ItemID.Sets.Explosives[selectedItem.netID] && args.Player.RecentFuse == 0 && selectedItem.createWall == 0) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (hammer2) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -533,7 +533,7 @@ namespace TShockAPI !p.Killed && Math.Abs((int)(Main.projectile[p.Index].position.X / 16f) - tileX) <= Math.Abs(Main.projectile[p.Index].velocity.X))) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (inconceivable rope coil) {0} {1} {2} selectedItem:{3} itemCreateTile:{4}", args.Player.Name, action, editData, selectedItem.netID, selectedItem.createTile); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -544,7 +544,7 @@ namespace TShockAPI requestedPlaceStyle > GetMaxPlaceStyle(editData)) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms1) {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -553,7 +553,7 @@ namespace TShockAPI if (selectedItem.netID == ItemID.IceRod && editData != TileID.MagicalIceBlock) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from using ice rod but not placing ice block {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; } /// If they aren't selecting the item which creates the tile, they're hacking. @@ -563,7 +563,7 @@ namespace TShockAPI if (selectedItem.netID != ItemID.IceRod && selectedItem.netID != ItemID.DirtBomb && selectedItem.netID != ItemID.StickyBomb) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from tile placement not matching selected item createTile {0} {1} {2} selectedItemID:{3} createTile:{4}", args.Player.Name, action, editData, selectedItem.netID, selectedItem.createTile); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -572,7 +572,7 @@ namespace TShockAPI if ((action == EditAction.PlaceWall || action == EditAction.ReplaceWall) && editData != selectedItem.createWall) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from wall placement not matching selected item createWall {0} {1} {2} selectedItemID:{3} createWall:{4}", args.Player.Name, action, editData, selectedItem.netID, selectedItem.createWall); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -582,7 +582,7 @@ namespace TShockAPI { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (chestcap) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendErrorMessage("The world's chest limit has been reached - unable to place more."); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -600,7 +600,7 @@ namespace TShockAPI && selectedItem.type != ItemID.WireKite) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from place wire from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -614,7 +614,7 @@ namespace TShockAPI && selectedItem.type != ItemID.MulticolorWrench) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from wire cutter from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -625,7 +625,7 @@ namespace TShockAPI if (selectedItem.type != ItemID.Actuator && !args.Player.TPlayer.autoActuator) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from actuator/presserator from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -635,7 +635,7 @@ namespace TShockAPI if (action == EditAction.KillWall || action == EditAction.ReplaceWall) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from sts allow cut from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -646,7 +646,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from disable from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -685,7 +685,7 @@ namespace TShockAPI } TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from explosives/fuses from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -699,7 +699,7 @@ namespace TShockAPI else { args.Player.Disable("Reached TileKill threshold.", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); } TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from tile kill threshold from {0}, (value: {1})", args.Player.Name, args.Player.TileKillThreshold); @@ -717,7 +717,7 @@ namespace TShockAPI else { args.Player.Disable("Reached TilePlace threshold.", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); } TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from tile place threshold from {0}, (value: {1})", args.Player.Name, args.Player.TilePlaceThreshold); @@ -729,7 +729,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from throttled from {0} {1} {2}", args.Player.Name, action, editData); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -763,7 +763,7 @@ namespace TShockAPI { TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from weird confusing flow control from {0}", args.Player.Name); TShock.Log.ConsoleDebug("If you're seeing this message and you know what that player did, please report it to TShock for further investigation."); - args.Player.SendTileSquare(tileX, tileY, 4); + args.Player.SendTileSquareCentered(tileX, tileY, 4); args.Handled = true; return; } @@ -1318,7 +1318,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from disabled from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1326,7 +1326,7 @@ namespace TShockAPI if (args.Player.SelectedItem.placeStyle != style) { TShock.Log.ConsoleError(string.Format("Bouncer / OnPlaceChest / rejected from invalid place style from {0}", args.Player.Name)); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1338,7 +1338,7 @@ namespace TShockAPI && (!TShock.Utils.HasWorldReachedMaxChests() && Main.tile[tileX, tileY].type != TileID.Dirt)) //Chest { TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from weird check from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1350,7 +1350,7 @@ namespace TShockAPI { TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from weird placement check from {0}", args.Player.Name); //Prevent a dresser from being placed on a teleporter, as this can cause client and server crashes. - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1359,7 +1359,7 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(tileX, tileY)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from invalid permission from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1367,7 +1367,7 @@ namespace TShockAPI if (!args.Player.IsInRange(tileX, tileY)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from range check from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 3); + args.Player.SendTileSquareCentered(tileX, tileY, 3); args.Handled = true; return; } @@ -1452,7 +1452,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected disabled from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1466,7 +1466,7 @@ namespace TShockAPI else { args.Player.Disable("Reached TileLiquid threshold.", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); } TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected from liquid threshold from {0} {1}/{2}", args.Player.Name, args.Player.TileLiquidThreshold, TShock.Config.Settings.TileLiquidThreshold); @@ -1539,7 +1539,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected bucket check 1 from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Spreading lava without holding a lava bucket", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1549,7 +1549,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected lava bucket from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Using banned lava bucket without permissions", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1559,7 +1559,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected bucket check 2 from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Spreading water without holding a water bucket", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1569,7 +1569,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected bucket check 3 from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Using banned water bucket without permissions", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1579,7 +1579,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected bucket check 4 from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Spreading honey without holding a honey bucket", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1589,7 +1589,7 @@ namespace TShockAPI TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected bucket check 5 from {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Using banned honey bucket without permissions", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1598,7 +1598,7 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(tileX, tileY)) { TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected build permission from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1606,7 +1606,7 @@ namespace TShockAPI if (!wasThereABombNearby && !args.Player.IsInRange(tileX, tileY, 16)) { TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected range checks from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1614,7 +1614,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected throttle from {0}", args.Player.Name); - args.Player.SendTileSquare(tileX, tileY, 1); + args.Player.SendTileSquareCentered(tileX, tileY, 1); args.Handled = true; return; } @@ -1926,7 +1926,7 @@ namespace TShockAPI if (type == TileID.FakeContainers && (style == 52 || style == 53)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected fake containers from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -1935,7 +1935,7 @@ namespace TShockAPI if (TShock.TileBans.TileIsBanned(type, args.Player)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected banned tiles from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 1); + args.Player.SendTileSquareCentered(x, y, 1); args.Player.SendErrorMessage("You do not have permission to place this tile."); args.Handled = true; return; @@ -1944,7 +1944,7 @@ namespace TShockAPI if (args.Player.Dead && TShock.Config.Settings.PreventDeadModification) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected dead people don't do things from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -1952,7 +1952,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected disabled from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -1963,7 +1963,7 @@ namespace TShockAPI if (type != args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].createTile) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected awkward tile creation/selection from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -1987,7 +1987,7 @@ namespace TShockAPI && !args.Player.HasBuildPermission(i, j)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected mad loop from {0}", args.Player.Name); - args.Player.SendTileSquare(i, j, 4); + args.Player.SendTileSquareCentered(i, j, 4); args.Handled = true; return; } @@ -2003,7 +2003,7 @@ namespace TShockAPI && !args.Player.IsInRange(x, y)) { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected range checks from {0}", args.Player.Name); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -2012,7 +2012,7 @@ namespace TShockAPI { TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected tile place threshold from {0} {1}/{2}", args.Player.Name, args.Player.TilePlaceThreshold, TShock.Config.Settings.TilePlaceThreshold); args.Player.Disable("Reached TilePlace threshold.", DisableFlags.WriteToLogAndConsole); - args.Player.SendTileSquare(x, y, 4); + args.Player.SendTileSquareCentered(x, y, 4); args.Handled = true; return; } @@ -2410,7 +2410,7 @@ namespace TShockAPI if ((args.Player.SelectedItem.type != args.ItemID && args.Player.ItemInHand.type != args.ItemID)) { TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected item not placed by hand from {0}", args.Player.Name); - args.Player.SendTileSquare(args.TileX, args.TileY, 1); + args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1); args.Handled = true; return; } @@ -2420,7 +2420,7 @@ namespace TShockAPI Item item = new Item(); item.netDefaults(args.ItemID); args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix); - args.Player.SendTileSquare(args.TileX, args.TileY, 1); + args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1); args.Handled = true; return; } @@ -2431,7 +2431,7 @@ namespace TShockAPI Item item = new Item(); item.netDefaults(args.ItemID); args.Player.GiveItemCheck(args.ItemID, item.Name, args.Stack, args.Prefix); - args.Player.SendTileSquare(args.TileX, args.TileY, 1); + args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1); args.Handled = true; return; } @@ -2439,7 +2439,7 @@ namespace TShockAPI if (!args.Player.IsInRange(args.TileX, args.TileY, range: 13)) // To my knowledge, max legit tile reach with accessories. { TShock.Log.ConsoleDebug("Bouncer / OnFoodPlatterTryPlacing rejected range checks from {0}", args.Player.Name); - args.Player.SendTileSquare(args.TileX, args.TileY, 1); + args.Player.SendTileSquareCentered(args.TileX, args.TileY, 1); args.Handled = true; return; } diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index a92994ab..ff0ed1ac 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -4899,7 +4899,7 @@ namespace TShockAPI try { - args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1); + args.Player.SendTileSquareCentered(boundaryPoint.X, boundaryPoint.Y, 1); } finally { @@ -4913,7 +4913,7 @@ namespace TShockAPI { foreach (Point boundaryPoint in Utils.Instance.EnumerateRegionBoundaries(regionArea)) if ((boundaryPoint.X + boundaryPoint.Y & 1) == 0) - args.Player.SendTileSquare(boundaryPoint.X, boundaryPoint.Y, 1); + args.Player.SendTileSquareCentered(boundaryPoint.X, boundaryPoint.Y, 1); Debug.Assert(boundaryHideTimer != null); boundaryHideTimer.Dispose(); @@ -5670,7 +5670,7 @@ namespace TShockAPI private static void SyncLocalArea(CommandArgs args) { - args.Player.SendTileSquare((int) args.Player.TileX, (int) args.Player.TileY, 32); + args.Player.SendTileSquareCentered(args.Player.TileX, args.Player.TileY, 32); args.Player.SendWarningMessage("Sync'd!"); return; } @@ -6676,7 +6676,7 @@ namespace TShockAPI } if (args.Parameters.Count == 1) { - args.Player.SendTileSquare(x - 2, y - 20, 25); + args.Player.SendTileSquareCentered(x - 2, y - 20, 25); args.Player.SendSuccessMessage("Tried to grow a " + name + "."); } } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index e2ab3a47..72770c93 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -3895,7 +3895,7 @@ namespace TShockAPI if (TShock.TileBans.TileIsBanned((short)TileID.LogicSensor, args.Player)) { - args.Player.SendTileSquare(x, y, 1); + args.Player.SendTileSquareCentered(x, y, 1); args.Player.SendErrorMessage("You do not have permission to place Logic Sensors."); return true; } diff --git a/TShockAPI/ItemBans.cs b/TShockAPI/ItemBans.cs index 3556d38c..2fa9e85e 100644 --- a/TShockAPI/ItemBans.cs +++ b/TShockAPI/ItemBans.cs @@ -199,7 +199,7 @@ namespace TShockAPI { if (args.Player.TPlayer.autoActuator && DataModel.ItemIsBanned("Actuator", args.Player)) { - args.Player.SendTileSquare(args.X, args.Y, 1); + args.Player.SendTileSquareCentered(args.X, args.Y, 1); args.Player.SendErrorMessage("You do not have permission to place actuators."); args.Handled = true; return; @@ -207,7 +207,7 @@ namespace TShockAPI if (DataModel.ItemIsBanned(EnglishLanguage.GetItemNameById(args.Player.SelectedItem.netID), args.Player)) { - args.Player.SendTileSquare(args.X, args.Y, 4); + args.Player.SendTileSquareCentered(args.X, args.Y, 4); args.Handled = true; return; } diff --git a/TShockAPI/RegionHandler.cs b/TShockAPI/RegionHandler.cs index 671e9933..48d5421a 100644 --- a/TShockAPI/RegionHandler.cs +++ b/TShockAPI/RegionHandler.cs @@ -171,7 +171,7 @@ namespace TShockAPI } // Revert all tile changes and handle the event - player.SendTileSquare(e.X, e.Y, 4); + player.SendTileSquareCentered(e.X, e.Y, 4); e.Handled = true; } @@ -190,7 +190,7 @@ namespace TShockAPI player.AwaitingTempPoint = 0; // Revert all tile changes and handle the event - player.SendTileSquare(e.X, e.Y, 4); + player.SendTileSquareCentered(e.X, e.Y, 4); e.Handled = true; } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 00ff790b..6a04bf0c 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -1227,7 +1227,7 @@ namespace TShockAPI y = 992; } - SendTileSquare((int)(x / 16), (int)(y / 16), 15); + SendTileSquareCentered((int)(x / 16), (int)(y / 16), 15); TPlayer.Teleport(new Vector2(x, y), style); NetMessage.SendData((int)PacketTypes.Teleport, -1, -1, NetworkText.Empty, 0, TPlayer.whoAmI, x, y, style); return true; @@ -1309,11 +1309,27 @@ namespace TShockAPI /// The y coordinate to send. /// The size square set of tiles to send. /// true if the tile square was sent successfully, else false + [Obsolete("This method may not send tiles the way you would expect it to. The (x,y) coordinates are the top left corner of the tile square, switch to " + nameof(SendTileSquareCentered) + " if you wish for the coordindates to be the center of the square.")] public virtual bool SendTileSquare(int x, int y, int size = 10) { return SendTileRect((short)x, (short)y, (byte)size, (byte)size); } + /// + /// Sends a tile square at a center location with a given size. + /// Typically used to revert changes by Bouncer through sending the + /// "old" version of modified data back to a client. + /// Prevents desync issues. + /// + /// The x coordinates of the center of the square. + /// The y coordinates of the center of the square. + /// The size square set of tiles to send. + /// true if the tile square was sent successfully, else false + public virtual bool SendTileSquareCentered(int x, int y, byte size = 10) + { + return SendTileRect((short)(x - (size / 2)), (short)(y - (size / 2)), size, size); + } + /// /// Sends a rectangle of tiles at a location with the given length and width. /// @@ -1348,7 +1364,7 @@ namespace TShockAPI public bool GiveItemCheck(int type, string name, int stack, int prefix = 0) { if ((TShock.ItemBans.DataModel.ItemIsBanned(name) && TShock.Config.Settings.PreventBannedItemSpawn) && - (TShock.ItemBans.DataModel.ItemIsBanned(name, this) || !TShock.Config.Settings.AllowAllowedGroupsToSpawnBannedItems)) + (TShock.ItemBans.DataModel.ItemIsBanned(name, this) || !TShock.Config.Settings.AllowAllowedGroupsToSpawnBannedItems)) return false; GiveItem(type, stack, prefix); diff --git a/TShockAPI/TSServerPlayer.cs b/TShockAPI/TSServerPlayer.cs index 9f59da49..d414d424 100644 --- a/TShockAPI/TSServerPlayer.cs +++ b/TShockAPI/TSServerPlayer.cs @@ -190,7 +190,7 @@ namespace TShockAPI // Send all players updated tile squares foreach (Vector2 coords in tiles.Keys) { - All.SendTileSquare((int)coords.X, (int)coords.Y, 3); + All.SendTileSquareCentered((int)coords.X, (int)coords.Y, 3); } }