diff --git a/.all-contributorsrc b/.all-contributorsrc index 8066f717..0c5fe2b1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -86,6 +86,33 @@ "contributions": [ "code" ] + }, + { + "login": "ColinBohn", + "name": "Colin Bohn", + "avatar_url": "https://avatars0.githubusercontent.com/u/1351268?v=4", + "profile": "http://colinbohn.me", + "contributions": [ + "code" + ] + }, + { + "login": "mrshroomy", + "name": "mrshroomy", + "avatar_url": "https://avatars0.githubusercontent.com/u/52048952?v=4", + "profile": "https://github.com/mrshroomy", + "contributions": [ + "test" + ] + }, + { + "login": "agentsparrow", + "name": "agentsparrow", + "avatar_url": "https://avatars0.githubusercontent.com/u/16114336?v=4", + "profile": "https://github.com/agentsparrow", + "contributions": [ + "test" + ] } ], "contributorsPerLine": 7, diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a10221..dae6c4ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,29 @@ This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large. -## Upcoming changes +## Upcoming release +* Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle) + +## TShock 4.4.0 (Pre-release 7 (Entangled)) +* Fixed bed spawn issues when trying to remove spawn point in SSC. (@Olink) +* Fixed Snake Flute. (@Olink) +* Fixed lava absorbant sponge not capturing lava. `LiquidSetEventArgs` now returns a `LiquidType` instead of a byte type. (@hakusaro) +* Fixed bottomless lava bucket from not being able to create lava. (@hakusaro) + * Ban a lava bucket to ban lava on the server entirely, until we figure out a better way to handle liquids. +* Fixed scarab bombs not detonating on pick style tiles. (@hakusaro) +* Fixed dirt bombs not creating dirt. (@hakusaro) +* Added a ridiculous amount of debug information. If you're experiencing any problems with 1.4 items being caught by the TShock anticheat system, please turn on DebugLogs in your config file and capture log data. It'll be extremely helpful in narrowing down precisely how to fix your problem. (@hakusaro) +* Released with entangled support for 1.4.0.4 based on @Patrikkk local build and latest snapshot gen-dev. (@hakusaro) + +## TShock 4.4.0 (Pre-release 6) +* Updates to OTAPI 2.0.0.35 (@DeathCradle). + +## TShock 4.4.0 (Pre-release 5) * Update player spawn related things to 1.4. `Terraria.Player.Spawn` method now has a required argument, `PlayerSpawnContext context`. (@AxeelAnder) * Make sqlite db path configurable. (@AxeelAnder) * Make TShock database MySQL 8 compatible by escaping column names in our IQueryBuilder code. (Name `Groups` is a reserved element in this version, which is used in our `Region` table.) +* Terraria 1.4.0.3 experimental support. (@Patrikkk) +* Updated changelog. (@hakusaro) ## TShock 4.4.0 (Pre-release 4) * Debug logging now provides ConsoleDebug and ILog has been updated to support the concept of debug logs. Debug logs are now controlled by `config.json` instead of by preprocessor debug flag. (@hakusaro) diff --git a/README.md b/README.md index abdb437d..2307ec8e 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,13 @@ TShock is a toolbox for Terraria servers and communities. That toolbox is jam packed with anti-cheat tools, server-side characters, groups, permissions, item bans, tons of commands, and limitless potential. It's one of a kind. -**We are currently polishing on Terraria 1.4.0.2 (curRelease = 226). For updates, check our [twitter, @Pryaxis](https://twitter.com/Pryaxis).** - -* Download: [Stable](https://github.com/TShock/TShock/releases) or [Experimental](#experimental-downloads). -* Download: [Plugins and tools](https://github.com/Pryaxis/plugins) that work with TShock, TSAPI, and Terraria. +* Download: [official](https://github.com/TShock/TShock/releases) or [experimental](#experimental-downloads). +* Download: [plugins and tools](https://github.com/Pryaxis/plugins) that work with TShock, TSAPI, and Terraria. * Read [the documentation](https://tshock.readme.io/) to quickly get up to speed. * Join [Discord](https://discord.gg/Cav9nYX). * Use the ancient [old forums](https://tshock.co/xf/index.php?resources/) to find old stuff. * Talk on [GitHub discussions](https://github.com/Pryaxis/TShock/discussions) to ask for help, chat, and other things. This is the best way to get help if Discord isn't your thing. +* For news, follow [@Pryaxis](https://twitter.com/Pryaxis) on Twitter. ---- @@ -266,6 +265,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Retrograde-i486

💻 +
Colin Bohn

💻 +
mrshroomy

⚠️ +
agentsparrow

⚠️ diff --git a/README_cn.md b/README_cn.md index caed48cb..70d3c33e 100644 --- a/README_cn.md +++ b/README_cn.md @@ -82,6 +82,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Retrograde-i486

💻 +
Colin Bohn

💻 +
mrshroomy

⚠️ +
agentsparrow

⚠️ diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 0231e9a9..d11cb758 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -205,7 +205,7 @@ namespace TShockAPI { if (editData < 0) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (editData check) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (editData check) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -213,7 +213,7 @@ namespace TShockAPI if (!TShock.Utils.TilePlacementValid(tileX, tileY)) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tile placement valid) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tile placement valid) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 1); args.Handled = true; return; @@ -221,14 +221,14 @@ namespace TShockAPI if (action == EditAction.KillTile && Main.tile[tileX, tileY].type == TileID.MagicalIceBlock) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit super accepted from (ice block) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit super accepted from (ice block) {0} {1} {2}", args.Player.Name, action, editData); args.Handled = false; return; } if (args.Player.Dead && TShock.Config.PreventDeadModification) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pdm) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pdm) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -242,7 +242,7 @@ namespace TShockAPI { if (TShock.TileBans.TileIsBanned(editData, args.Player)) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tb) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (tb) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 1); args.Player.SendErrorMessage("You do not have permission to place this tile."); args.Handled = true; @@ -257,7 +257,7 @@ namespace TShockAPI // If the tile is an axe tile and they aren't selecting an axe, they're hacking. 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}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (axe) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -265,7 +265,7 @@ namespace TShockAPI // If the tile is a hammer tile and they aren't selecting a hammer, they're hacking. 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}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (hammer) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -275,7 +275,7 @@ namespace TShockAPI else if (tile.type != TileID.ItemFrame && !Main.tileAxe[tile.type] && !Main.tileHammer[tile.type] && tile.wall == 0 && args.Player.TPlayer.mount.Type != 8 && selectedItem.pick == 0 && !ItemID.Sets.Explosives[selectedItem.netID] && args.Player.RecentFuse == 0) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pick) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (pick) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -286,7 +286,7 @@ namespace TShockAPI // If they aren't selecting a hammer, they could be hacking. 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}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (hammer2) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 1); args.Handled = true; return; @@ -302,7 +302,7 @@ namespace TShockAPI (MaxPlaceStyles.ContainsKey(editData) && style > MaxPlaceStyles[editData]) && (ExtraneousPlaceStyles.ContainsKey(editData) && style > ExtraneousPlaceStyles[editData])) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms1) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms1) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -313,23 +313,27 @@ namespace TShockAPI (editData != (action == EditAction.PlaceTile ? selectedItem.createTile : selectedItem.createWall) && !(ropeCoilPlacements.ContainsKey(selectedItem.netID) && editData == ropeCoilPlacements[selectedItem.netID]))) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms2) {0}", args.Player.Name); - - args.Player.SendTileSquare(tileX, tileY, 4); - args.Handled = true; - return; + // Rather than attempting to figure out what the above if statement does, we'll just patch it + // Adds exception to this check to allow dirt bombs to create dirt tiles + if (!(selectedItem.netID == ItemID.DirtBomb && action == EditAction.PlaceTile && editData == TileID.Dirt)) + { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms2) {0} {1} {2}", args.Player.Name, action, editData); + args.Player.SendTileSquare(tileX, tileY, 4); + args.Handled = true; + return; + } } if (editData >= (action == EditAction.PlaceTile ? Main.maxTileSets : Main.maxWallTypes)) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms3) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (ms3) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; } if (action == EditAction.PlaceTile && (editData == TileID.PiggyBank || editData == TileID.Safes) && Main.ServerSideCharacter) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (sscprotect) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (sscprotect) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendErrorMessage("You cannot place this tile because server side characters are enabled."); args.Player.SendTileSquare(tileX, tileY, 3); args.Handled = true; @@ -339,7 +343,7 @@ namespace TShockAPI { if (TShock.Utils.HasWorldReachedMaxChests()) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (chestcap) {0}", args.Player.Name); + 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.Handled = true; @@ -348,7 +352,7 @@ namespace TShockAPI if ((TShock.Utils.TilePlacementValid(tileX, tileY + 1) && Main.tile[tileX, tileY + 1].type == TileID.Boulder) || (TShock.Utils.TilePlacementValid(tileX + 1, tileY + 1) && Main.tile[tileX + 1, tileY + 1].type == TileID.Boulder)) { - TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (validplacement) {0}", args.Player.Name); + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from (validplacement) {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 3); args.Handled = true; return; @@ -366,6 +370,7 @@ namespace TShockAPI && selectedItem.type != ItemID.MulticolorWrench && 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.Handled = true; return; @@ -379,6 +384,7 @@ namespace TShockAPI && selectedItem.type != ItemID.WireKite && 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.Handled = true; return; @@ -389,6 +395,7 @@ namespace TShockAPI // If they aren't selecting the actuator and don't have the Presserator equipped, they're hacking. 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.Handled = true; return; @@ -398,6 +405,7 @@ namespace TShockAPI { if (action == EditAction.KillWall) { + 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.Handled = true; return; @@ -408,6 +416,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from wire cutter from {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -416,6 +425,7 @@ namespace TShockAPI if (!args.Player.HasModifiedIceSuccessfully(tileX, tileY, editData, action) && !args.Player.HasBuildPermission(tileX, tileY)) { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from ice/build from {0} {1} {2}", args.Player.Name, action, editData); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; return; @@ -435,6 +445,14 @@ namespace TShockAPI return; } + // Dirt bomb makes dirt everywhere + if ((action == EditAction.PlaceTile || action == EditAction.SlopeTile) && editData == TileID.Dirt && args.Player.RecentFuse > 0) + { + args.Handled = false; + return; + } + + 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.Handled = true; return; @@ -442,6 +460,8 @@ namespace TShockAPI if (args.Player.TileKillThreshold >= TShock.Config.TileKillThreshold) { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from tile kill threshold from {0}, (value: {1})", args.Player.Name, args.Player.TileKillThreshold); + TShock.Log.ConsoleDebug("If this player wasn't hacking, please report the damage value they were disabled for to TShock so we can improve this!"); args.Player.Disable("Reached TileKill threshold.", DisableFlags.WriteToLogAndConsole); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; @@ -450,6 +470,8 @@ namespace TShockAPI if (args.Player.TilePlaceThreshold >= TShock.Config.TilePlaceThreshold) { + TShock.Log.ConsoleDebug("Bouncer / OnTileEdit rejected from tile place threshold from {0}, (value: {1})", args.Player.Name, args.Player.TilePlaceThreshold); + TShock.Log.ConsoleDebug("If this player wasn't hacking, please report the damage value they were disabled for to TShock so we can improve this!"); args.Player.Disable("Reached TilePlace threshold.", DisableFlags.WriteToLogAndConsole); args.Player.SendTileSquare(tileX, tileY, 4); args.Handled = true; @@ -458,6 +480,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.Handled = true; return; @@ -486,6 +509,8 @@ namespace TShockAPI } catch { + 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.Handled = true; return; @@ -503,6 +528,7 @@ namespace TShockAPI if (args.Player.HasPermission(Permissions.allowclientsideworldedit)) { + TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected clientside world edit from {0}", args.Player.Name); args.Handled = false; return; } @@ -511,12 +537,14 @@ namespace TShockAPI // IIRC it's because 5 means a 5x5 square which is normal for a tile square, and anything bigger is a non-vanilla tile modification attempt if (size > 5) { + TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from non-vanilla tilemod from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from throttle from {0}", args.Player.Name); args.Player.SendTileSquare(tileX, tileY, size); args.Handled = true; return; @@ -524,6 +552,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from being disabled from {0}", args.Player.Name); args.Player.SendTileSquare(tileX, tileY, size); args.Handled = true; return; @@ -682,6 +711,7 @@ namespace TShockAPI args.Player.SendTileSquare(tileX, tileY, size); } + TShock.Log.ConsoleDebug("Bouncer / SendTileSquare rejected from spaghetti from {0}", args.Player.Name); args.Handled = true; } @@ -703,6 +733,7 @@ namespace TShockAPI { // Causes item duplications. Will be re added later if necessary //args.Player.SendData(PacketTypes.ItemDrop, "", id); + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from attempt crash from {0}", args.Player.Name); args.Handled = true; return; } @@ -712,6 +743,8 @@ namespace TShockAPI // will break item pickups on the client. if (prefix > PrefixID.Count) { + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from prefix check from {0}", args.Player.Name); + args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -725,6 +758,7 @@ namespace TShockAPI { // Causes item duplications. Will be re added if necessary //args.Player.SendData(PacketTypes.ItemDrop, "", id); + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from dupe range check from {0}", args.Player.Name); args.Handled = true; return; } @@ -735,6 +769,7 @@ namespace TShockAPI if (!args.Player.IsInRange((int)(pos.X / 16f), (int)(pos.Y / 16f))) { + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from range check from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -744,6 +779,7 @@ namespace TShockAPI // only if the client isn't picking up the item if (Main.item[id].active && Main.item[id].netID != type) { + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from item drop/pickup check from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -753,6 +789,7 @@ namespace TShockAPI item.netDefaults(type); if ((stacks > item.maxStack || stacks <= 0) || (TShock.Itembans.ItemIsBanned(EnglishLanguage.GetItemNameById(item.type), args.Player) && !args.Player.HasPermission(Permissions.allowdroppingbanneditems))) { + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from drop item ban check / max stack check / min stack check from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -763,6 +800,7 @@ namespace TShockAPI { //Player is probably trying to sneak items onto the server in their hands!!! TShock.Log.ConsoleInfo("Player {0} tried to sneak {1} onto the server!", args.Player.Name, item.Name); + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from sneaky from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -771,6 +809,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnItemDrop rejected from disabled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ItemDrop, "", id); args.Handled = true; return; @@ -793,6 +832,7 @@ namespace TShockAPI if (index > Main.maxProjectiles) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from above projectile limit from {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -801,6 +841,7 @@ namespace TShockAPI if (TShock.ProjectileBans.ProjectileIsBanned(type, args.Player)) { args.Player.Disable(String.Format("Player does not have permission to create projectile {0}.", type), DisableFlags.WriteToLogAndConsole); + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from permission check from {0} {1}", args.Player.Name, type); args.Player.SendErrorMessage("You do not have permission to create that projectile."); args.Player.RemoveProjectile(ident, owner); args.Handled = true; @@ -810,6 +851,7 @@ namespace TShockAPI if (damage > TShock.Config.MaxProjDamage && !args.Player.HasPermission(Permissions.ignoredamagecap)) { args.Player.Disable(String.Format("Projectile damage is higher than {0}.", TShock.Config.MaxProjDamage), DisableFlags.WriteToLogAndConsole); + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from projectile damage limit from {0} {1}/{2}", args.Player.Name, damage, TShock.Config.MaxProjDamage); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -817,6 +859,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from disabled from {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -838,6 +881,7 @@ namespace TShockAPI // possible for players to create. (Source: Ijwu, QuiCM) if (Main.projHostile[type]) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from hostile projectile from {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -846,6 +890,7 @@ namespace TShockAPI // Tombstones should never be permitted by players if (type == ProjectileID.Tombstone) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from tombstones from {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -865,10 +910,12 @@ namespace TShockAPI || (type >= ProjectileID.MartianTurretBolt && type <= ProjectileID.RayGunnerLaser) || type == ProjectileID.CultistBossLightningOrb) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from weird check from {0} {1}", args.Player.Name, type); TShock.Log.Debug("Certain projectiles have been ignored for cheat detection."); } else { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile please report to tshock about this! normally this is a reject from {0} {1}", args.Player.Name, type); // args.Player.Disable(String.Format("Does not have projectile permission to update projectile. ({0})", type), DisableFlags.WriteToLogAndConsole); // args.Player.RemoveProjectile(ident, owner); } @@ -879,6 +926,7 @@ namespace TShockAPI if (args.Player.ProjectileThreshold >= TShock.Config.ProjectileThreshold) { args.Player.Disable("Reached projectile update threshold.", DisableFlags.WriteToLogAndConsole); + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from proj update threshold from {0} {1}/{2}", args.Player.Name, args.Player.ProjectileThreshold, TShock.Config.ProjectileThreshold); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -886,6 +934,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnNewProjectile rejected from bouncer throttle from {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); args.Handled = true; return; @@ -906,7 +955,9 @@ namespace TShockAPI if ((type == ProjectileID.Bomb || type == ProjectileID.Dynamite || type == ProjectileID.StickyBomb - || type == ProjectileID.StickyDynamite)) + || type == ProjectileID.StickyDynamite + || type == ProjectileID.ScarabBomb + || type == ProjectileID.DirtBomb)) { // Denotes that the player has recently set a fuse - used for cheat detection. args.Player.RecentFuse = 10; @@ -935,11 +986,13 @@ namespace TShockAPI if (TShock.Config.KickOnDamageThresholdBroken) { args.Player.Kick(string.Format("NPC damage exceeded {0}.", TShock.Config.MaxDamage)); + TShock.Log.ConsoleDebug("Bouncer / OnNPCStrike rejected from kodtb from {0} {1}/{2}", args.Player.Name, damage, TShock.Config.MaxDamage); args.Handled = true; return; } else { + TShock.Log.ConsoleDebug("Bouncer / OnNPCStrike rejected from dtb from {0} {1}/{2}", args.Player.Name, damage, TShock.Config.MaxDamage); args.Player.Disable(String.Format("NPC damage exceeded {0}.", TShock.Config.MaxDamage), DisableFlags.WriteToLogAndConsole); } args.Player.SendData(PacketTypes.NpcUpdate, "", id); @@ -949,6 +1002,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCStrike rejected from disabled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.NpcUpdate, "", id); args.Handled = true; return; @@ -957,6 +1011,7 @@ namespace TShockAPI if (TShock.Config.RangeChecks && !args.Player.IsInRange((int)(Main.npc[id].position.X / 16f), (int)(Main.npc[id].position.Y / 16f), 128)) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCStrike rejected from range checks from {0}", args.Player.Name); args.Player.SendData(PacketTypes.NpcUpdate, "", id); args.Handled = true; return; @@ -964,6 +1019,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCStrike rejected from bouncer throttle from {0}", args.Player.Name); args.Player.SendData(PacketTypes.NpcUpdate, "", id); args.Handled = true; return; @@ -977,12 +1033,14 @@ namespace TShockAPI { if (args.ProjectileIndex < 0) { + TShock.Log.ConsoleDebug("Bouncer / OnProjectileKill rejected from negative projectile index from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnProjectileKill rejected from disabled from {0}", args.Player.Name); args.Player.RemoveProjectile(args.ProjectileIdentity, args.ProjectileOwner); args.Handled = true; return; @@ -990,6 +1048,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnProjectileKill rejected from bouncer throttle from {0}", args.Player.Name); args.Player.RemoveProjectile(args.ProjectileIdentity, args.ProjectileOwner); args.Handled = true; return; @@ -1009,12 +1068,14 @@ namespace TShockAPI if (args.Player.TPlayer.chest != id) { + TShock.Log.ConsoleDebug("Bouncer / OnChestItemChange rejected from chest mismatch from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnChestItemChange rejected from disable from {0}", args.Player.Name); args.Player.SendData(PacketTypes.ChestItem, "", id, slot); args.Handled = true; return; @@ -1022,12 +1083,14 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(Main.chest[id].x, Main.chest[id].y) && TShock.Config.RegionProtectChests) { + TShock.Log.ConsoleDebug("Bouncer / OnChestItemChange rejected from region protection? from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.IsInRange(Main.chest[id].x, Main.chest[id].y)) { + TShock.Log.ConsoleDebug("Bouncer / OnChestItemChange rejected from range check from {0}", args.Player.Name); args.Handled = true; return; } @@ -1040,18 +1103,21 @@ namespace TShockAPI { if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnChestOpen rejected from disabled from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.IsInRange(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnChestOpen rejected from range check from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.HasBuildPermission(args.X, args.Y) && TShock.Config.RegionProtectChests) { + TShock.Log.ConsoleDebug("Bouncer / OnChestOpen rejected from region check from {0}", args.Player.Name); args.Handled = true; return; } @@ -1071,12 +1137,14 @@ namespace TShockAPI if (!TShock.Utils.TilePlacementValid(tileX, tileY) || (args.Player.Dead && TShock.Config.PreventDeadModification)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from invalid check from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceChest rejected from disabled from {0}", args.Player.Name); args.Player.SendTileSquare(tileX, tileY, 3); args.Handled = true; return; @@ -1088,6 +1156,7 @@ namespace TShockAPI && Main.tile[tileX, tileY].type != TileID.Containers2 && (!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.Handled = true; return; @@ -1098,6 +1167,7 @@ namespace TShockAPI if ((TShock.Utils.TilePlacementValid(tileX, tileY + 1) && Main.tile[tileX, tileY + 1].type == TileID.Teleporter) || (TShock.Utils.TilePlacementValid(tileX + 1, tileY + 1) && Main.tile[tileX + 1, tileY + 1].type == TileID.Teleporter)) { + 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.Handled = true; @@ -1107,6 +1177,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.Handled = true; return; @@ -1114,6 +1185,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.Handled = true; return; @@ -1150,6 +1222,7 @@ namespace TShockAPI || (args.Zone2[4] && !hasStardustTower) ) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerZone rejected from {0}", args.Player.Name); args.Handled = true; return; } @@ -1163,6 +1236,7 @@ namespace TShockAPI { if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerAnimation rejected from disabled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index); args.Handled = true; return; @@ -1170,6 +1244,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerAnimation rejected from throttle from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index); args.Handled = true; return; @@ -1184,16 +1259,18 @@ namespace TShockAPI int tileX = args.TileX; int tileY = args.TileY; byte amount = args.Amount; - byte type = args.Type; + LiquidType type = args.Type; if (!TShock.Utils.TilePlacementValid(tileX, tileY) || (args.Player.Dead && TShock.Config.PreventDeadModification)) { + TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected invalid check from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected disabled from {0}", args.Player.Name); args.Player.SendTileSquare(tileX, tileY, 1); args.Handled = true; return; @@ -1201,6 +1278,7 @@ namespace TShockAPI if (args.Player.TileLiquidThreshold >= TShock.Config.TileLiquidThreshold) { + TShock.Log.ConsoleDebug("Bouncer / OnLiquidSet rejected from liquid threshold from {0} {1}/{2}", args.Player.Name, args.Player.TileLiquidThreshold, TShock.Config.TileLiquidThreshold); args.Player.Disable("Reached TileLiquid threshold.", DisableFlags.WriteToLogAndConsole); args.Player.SendTileSquare(tileX, tileY, 1); args.Handled = true; @@ -1217,30 +1295,40 @@ namespace TShockAPI if (amount != 0) { int bucket = -1; - if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.EmptyBucket) + int selectedItemType = args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type; + if (selectedItemType == ItemID.EmptyBucket) { bucket = 0; } - else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.WaterBucket) + else if (selectedItemType == ItemID.WaterBucket) { bucket = 1; } - else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.LavaBucket) + else if (selectedItemType == ItemID.LavaBucket) { bucket = 2; } - else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.HoneyBucket) + else if (selectedItemType == ItemID.HoneyBucket) { bucket = 3; } - else if (args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.BottomlessBucket || - args.Player.TPlayer.inventory[args.Player.TPlayer.selectedItem].type == ItemID.SuperAbsorbantSponge) + else if (selectedItemType == ItemID.BottomlessBucket || + selectedItemType == ItemID.SuperAbsorbantSponge) { bucket = 4; } - - if (type == 1 && !(bucket == 2 || bucket == 0)) + else if (selectedItemType == ItemID.LavaAbsorbantSponge) { + bucket = 5; + } + else if (selectedItemType == ItemID.BottomlessLavaBucket) + { + bucket = 6; + } + + if (type == LiquidType.Lava && !(bucket == 2 || bucket == 0 || bucket == 5 || bucket == 6)) + { + 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); @@ -1248,8 +1336,9 @@ namespace TShockAPI return; } - if (type == 1 && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)) + if (type == LiquidType.Lava && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)) { + 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); @@ -1257,8 +1346,9 @@ namespace TShockAPI return; } - if (type == 0 && !(bucket == 1 || bucket == 0 || bucket == 4)) + if (type == LiquidType.Water && !(bucket == 1 || bucket == 0 || bucket == 4)) { + 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); @@ -1266,8 +1356,9 @@ namespace TShockAPI return; } - if (type == 0 && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player)) + if (type == LiquidType.Water && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player)) { + 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); @@ -1275,8 +1366,9 @@ namespace TShockAPI return; } - if (type == 2 && !(bucket == 3 || bucket == 0)) + if (type == LiquidType.Honey && !(bucket == 3 || bucket == 0)) { + 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); @@ -1284,8 +1376,9 @@ namespace TShockAPI return; } - if (type == 2 && TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player)) + if (type == LiquidType.Honey && TShock.Itembans.ItemIsBanned("Honey Bucket", args.Player)) { + 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); @@ -1296,6 +1389,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.Handled = true; return; @@ -1303,6 +1397,7 @@ namespace TShockAPI if (!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.Handled = true; return; @@ -1310,6 +1405,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.Handled = true; return; @@ -1327,12 +1423,14 @@ namespace TShockAPI if (TShock.Players[id] == null) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected null check"); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected disabled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); args.Handled = true; return; @@ -1340,6 +1438,7 @@ namespace TShockAPI if (id >= Main.maxPlayers) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected player cap from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); args.Handled = true; return; @@ -1347,6 +1446,7 @@ namespace TShockAPI if (!TShock.Players[id].TPlayer.hostile || !Main.pvpBuff[type]) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected hostile/pvp from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); args.Handled = true; return; @@ -1354,6 +1454,7 @@ namespace TShockAPI if (!args.Player.IsInRange(TShock.Players[id].TileX, TShock.Players[id].TileY, 50)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected range check from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); args.Handled = true; return; @@ -1361,6 +1462,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected throttled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerAddBuff, "", id); args.Handled = true; return; @@ -1368,6 +1470,7 @@ namespace TShockAPI if (WhitelistBuffMaxTime[type] > 0 && time <= WhitelistBuffMaxTime[type]) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerBuff rejected buff time whitelists from {0}", args.Player.Name); args.Handled = false; return; } @@ -1384,6 +1487,7 @@ namespace TShockAPI if (id >= Main.npc.Length) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCAddBuff rejected out of bounds NPC update from {0}", args.Player.Name); args.Handled = true; return; } @@ -1392,12 +1496,14 @@ namespace TShockAPI if (npc == null) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCAddBuff rejected null npc from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnNPCAddBuff rejected disabled from {0}", args.Player.Name); args.Handled = true; return; } @@ -1427,7 +1533,7 @@ namespace TShockAPI if (detectedNPCBuffTimeCheat) { - + TShock.Log.ConsoleDebug("Bouncer / OnNPCAddBuff rejected abnormal buff ({1}) from {0}", args.Player.Name, type); args.Player.Kick($"Added buff to NPC abnormally.", true); args.Handled = true; } @@ -1447,6 +1553,7 @@ namespace TShockAPI { args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); + TShock.Log.ConsoleDebug("Bouncer / OnUpdateNPCHome rejected npc home build permission from {0}", args.Player.Name); args.Handled = true; return; } @@ -1455,6 +1562,7 @@ namespace TShockAPI { args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); + TShock.Log.ConsoleDebug("Bouncer / OnUpdateNPCHome rejected range checks from {0}", args.Player.Name); args.Handled = true; return; } @@ -1470,6 +1578,7 @@ namespace TShockAPI if (amount <= 0 || Main.player[plr] == null || !Main.player[plr].active) { + TShock.Log.ConsoleDebug("Bouncer / OnHealOtherPlayer rejected null checks"); args.Handled = true; return; } @@ -1479,6 +1588,7 @@ namespace TShockAPI // and the healing you can do with that is 20% of your damage. if (amount > TShock.Config.MaxDamage * 0.2) { + TShock.Log.ConsoleDebug("Bouncer / OnUpdateNPCHome 0.2 check from {0}", args.Player.Name); args.Player.Disable("HealOtherPlayer cheat attempt!", DisableFlags.WriteToLogAndConsole); args.Handled = true; return; @@ -1486,6 +1596,7 @@ namespace TShockAPI if (args.Player.HealOtherThreshold > TShock.Config.HealOtherThreshold) { + TShock.Log.ConsoleDebug("Bouncer / OnUpdateNPCHome rejected heal other threshold from {0} {1}/{2}", args.Player.Name, args.Player.HealOtherThreshold, TShock.Config.HealOtherThreshold); args.Player.Disable("Reached HealOtherPlayer threshold.", DisableFlags.WriteToLogAndConsole); args.Handled = true; return; @@ -1493,6 +1604,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled() || args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnUpdateNPCHome rejected disabled/throttled from {0}", args.Player.Name); args.Handled = true; return; } @@ -1516,18 +1628,21 @@ namespace TShockAPI if (type < 0 || type >= Main.maxTileSets) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected out of bounds tile from {0}", args.Player.Name); args.Handled = true; return; } if (x < 0 || x >= Main.maxTilesX) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected out of bounds tile x from {0}", args.Player.Name); args.Handled = true; return; } if (y < 0 || y >= Main.maxTilesY) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected out of bounds tile y from {0}", args.Player.Name); args.Handled = true; return; } @@ -1536,6 +1651,7 @@ namespace TShockAPI //These two items cause localised lag and rendering issues 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.Handled = true; return; @@ -1544,6 +1660,7 @@ namespace TShockAPI // TODO: REMOVE. This does NOT look like Bouncer code. 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.SendErrorMessage("You do not have permission to place this tile."); args.Handled = true; @@ -1552,6 +1669,7 @@ namespace TShockAPI if (!TShock.Utils.TilePlacementValid(x, y)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected valid placements from {0}", args.Player.Name); args.Player.SendTileSquare(x, y, 1); args.Handled = true; return; @@ -1559,6 +1677,7 @@ namespace TShockAPI if (args.Player.Dead && TShock.Config.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.Handled = true; return; @@ -1566,6 +1685,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.Handled = true; return; @@ -1576,6 +1696,7 @@ namespace TShockAPI // without selecting the right item. 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.Handled = true; return; @@ -1584,6 +1705,7 @@ namespace TShockAPI TileObjectData tileData = TileObjectData.GetTileData(type, style, 0); if (tileData == null) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected null tile data from {0}", args.Player.Name); args.Handled = true; return; } @@ -1598,6 +1720,7 @@ namespace TShockAPI if (!args.Player.HasModifiedIceSuccessfully(i, j, type, EditAction.PlaceTile) && !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.Handled = true; return; @@ -1612,6 +1735,7 @@ namespace TShockAPI || type != TileID.WebRope) && !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.Handled = true; return; @@ -1619,6 +1743,7 @@ namespace TShockAPI if (args.Player.TilePlaceThreshold >= TShock.Config.TilePlaceThreshold) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceObject rejected tile place threshold from {0} {1}/{2}", args.Player.Name, args.Player.TilePlaceThreshold, TShock.Config.TilePlaceThreshold); args.Player.Disable("Reached TilePlace threshold.", DisableFlags.WriteToLogAndConsole); args.Player.SendTileSquare(x, y, 4); args.Handled = true; @@ -1642,18 +1767,21 @@ namespace TShockAPI { if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceTileEntity rejected disabled from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.HasBuildPermission(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceTileEntity rejected permissions from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.IsInRange(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceTileEntity rejected range checks from {0}", args.Player.Name); args.Handled = true; return; } @@ -1666,6 +1794,7 @@ namespace TShockAPI { if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceItemFrame rejected disabled from {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1); args.Handled = true; return; @@ -1673,6 +1802,7 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceItemFrame rejected permissions from {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1); args.Handled = true; return; @@ -1680,6 +1810,7 @@ namespace TShockAPI if (!args.Player.IsInRange(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlaceItemFrame rejected range checks from {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.UpdateTileEntity, -1, -1, NetworkText.Empty, args.ItemFrame.ID, 0, 1); args.Handled = true; return; @@ -1692,6 +1823,7 @@ namespace TShockAPI //belongs to the player who sent the packet. if (args.Player.Index != args.TargetPlayerIndex) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerPortalTeleport rejected untargetable teleport from {0}", args.Player.Name); //If the player who sent the packet is not the player being teleported, cancel this packet args.Player.Disable("Malicious portal attempt.", DisableFlags.WriteToLogAndConsole); //Todo: this message is not particularly clear - suggestions wanted args.Handled = true; @@ -1702,6 +1834,7 @@ namespace TShockAPI if (args.NewPosition.X > Main.maxTilesX || args.NewPosition.X < 0 || args.NewPosition.Y > Main.maxTilesY || args.NewPosition.Y < 0) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerPortalTeleport rejected teleport out of bounds from {0}", args.Player.Name); args.Handled = true; return; } @@ -1709,6 +1842,7 @@ namespace TShockAPI //May as well reject teleport attempts if the player is being throttled if (args.Player.IsBeingDisabled() || args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerPortalTeleport rejected disabled/throttled from {0}", args.Player.Name); args.Handled = true; return; } @@ -1721,24 +1855,28 @@ namespace TShockAPI { if (args.X < 0 || args.Y < 0 || args.X >= Main.maxTilesX || args.Y >= Main.maxTilesY) { + TShock.Log.ConsoleDebug("Bouncer / OnGemLockToggle rejected boundaries check from {0}", args.Player.Name); args.Handled = true; return; } if (!TShock.Utils.TilePlacementValid(args.X, args.Y) || (args.Player.Dead && TShock.Config.PreventDeadModification)) { + TShock.Log.ConsoleDebug("Bouncer / OnGemLockToggle invalid placement/deadmod from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnGemLockToggle rejected disabled from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.HasBuildPermission(args.X, args.Y)) { + TShock.Log.ConsoleDebug("Bouncer / OnGemLockToggle rejected permissions check from {0}", args.Player.Name); args.Handled = true; return; } @@ -1772,18 +1910,21 @@ namespace TShockAPI if (!TShock.Utils.TilePlacementValid(x, y) || (args.Player.Dead && TShock.Config.PreventDeadModification)) { + TShock.Log.ConsoleDebug("Bouncer / OnMassWireOperation rejected valid placement from {0}", args.Player.Name); args.Handled = true; return; } if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnMassWireOperation rejected disabled from {0}", args.Player.Name); args.Handled = true; return; } if (!args.Player.HasBuildPermission(x, y)) { + TShock.Log.ConsoleDebug("Bouncer / OnMassWireOperation rejected build perms from {0}", args.Player.Name); args.Handled = true; return; } @@ -1803,6 +1944,7 @@ namespace TShockAPI if (id >= Main.maxPlayers || TShock.Players[id] == null) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected null check"); args.Handled = true; return; } @@ -1811,12 +1953,14 @@ namespace TShockAPI { if (TShock.Config.KickOnDamageThresholdBroken) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected damage threshold from {0} {1}/{2}", args.Player.Name, damage, TShock.Config.MaxDamage); args.Player.Kick(string.Format("Player damage exceeded {0}.", TShock.Config.MaxDamage)); args.Handled = true; return; } else { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected damage threshold2 from {0} {1}/{2}", args.Player.Name, damage, TShock.Config.MaxDamage); args.Player.Disable(String.Format("Player damage exceeded {0}.", TShock.Config.MaxDamage), DisableFlags.WriteToLogAndConsole); } args.Player.SendData(PacketTypes.PlayerHp, "", id); @@ -1827,6 +1971,7 @@ namespace TShockAPI if (!TShock.Players[id].TPlayer.hostile && pvp && id != args.Player.Index) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected hostile from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerHp, "", id); args.Player.SendData(PacketTypes.PlayerUpdate, "", id); args.Handled = true; @@ -1835,6 +1980,7 @@ namespace TShockAPI if (args.Player.IsBeingDisabled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected disabled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerHp, "", id); args.Player.SendData(PacketTypes.PlayerUpdate, "", id); args.Handled = true; @@ -1843,6 +1989,7 @@ namespace TShockAPI if (!args.Player.IsInRange(TShock.Players[id].TileX, TShock.Players[id].TileY, 100)) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected range checks from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerHp, "", id); args.Player.SendData(PacketTypes.PlayerUpdate, "", id); args.Handled = true; @@ -1851,6 +1998,7 @@ namespace TShockAPI if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("Bouncer / OnPlayerDamage rejected throttled from {0}", args.Player.Name); args.Player.SendData(PacketTypes.PlayerHp, "", id); args.Player.SendData(PacketTypes.PlayerUpdate, "", id); args.Handled = true; @@ -1870,6 +2018,7 @@ namespace TShockAPI if (damage > 20000) //Abnormal values have the potential to cause infinite loops in the server. { + TShock.Log.ConsoleDebug("Bouncer / OnKillMe rejected high damage from {0} {1}", args.Player.Name, damage); args.Player.Kick("Failed to shade polygon normals.", true, true); TShock.Log.ConsoleError("Death Exploit Attempt: Damage {0}", damage); args.Handled = true; @@ -1878,6 +2027,7 @@ namespace TShockAPI if (id >= Main.maxPlayers) { + TShock.Log.ConsoleDebug("Bouncer / OnKillMe rejected index check from {0}", args.Player.Name); args.Handled = true; return; } @@ -1887,6 +2037,7 @@ namespace TShockAPI { if (playerDeathReason.GetDeathText(TShock.Players[id].Name).ToString().Length > 500) { + TShock.Log.ConsoleDebug("Bouncer / OnKillMe rejected bad length death text from {0}", args.Player.Name); TShock.Players[id].Kick("Death reason outside of normal bounds.", true); args.Handled = true; return; diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 636f269d..1dc490d8 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -4996,23 +4996,17 @@ namespace TShockAPI { if (TShock.SetupToken == 0) { - if (args.Player.Group.Name == new SuperAdminGroup().Name) - args.Player.SendInfoMessage("The initial setup system is already disabled."); - else - { - args.Player.SendWarningMessage("The initial setup system is disabled. This incident has been logged."); - TShock.Log.Warn("{0} attempted to use the initial setup system even though it's disabled.", args.Player.IP); - return; - } + args.Player.SendWarningMessage("The initial setup system is disabled. This incident has been logged."); + args.Player.SendWarningMessage("If you are locked out of all admin accounts, ask for help on https://tshock.co/"); + TShock.Log.Warn("{0} attempted to use the initial setup system even though it's disabled.", args.Player.IP); + return; } - // If the user account is already a superadmin (permanent), disable the system + // If the user account is already logged in, turn off the setup system if (args.Player.IsLoggedIn && args.Player.tempGroup == null) { args.Player.SendSuccessMessage("Your new account has been verified, and the {0}setup system has been turned off.", Specifier); - args.Player.SendSuccessMessage("You can always use the {0}user command to manage players.", Specifier); - args.Player.SendSuccessMessage("The setup system will remain disabled as long as a superadmin exists (even if you delete setup.lock)."); - args.Player.SendSuccessMessage("Share your server, talk with other admins, and more on GitHub! -- https://tshock.co/"); + args.Player.SendSuccessMessage("Share your server, talk with admins, and chill on GitHub & Discord. -- https://tshock.co/"); args.Player.SendSuccessMessage("Thank you for using TShock for Terraria!"); FileTools.CreateFile(Path.Combine(TShock.SavePath, "setup.lock")); File.Delete(Path.Combine(TShock.SavePath, "setup-code.txt")); @@ -5038,11 +5032,11 @@ namespace TShockAPI args.Player.tempGroup = new SuperAdminGroup(); args.Player.SendInfoMessage("Temporary system access has been given to you, so you can run one command."); - args.Player.SendInfoMessage("Please use the following to create a permanent account for you."); - args.Player.SendInfoMessage("{0}user add owner", Specifier); + args.Player.SendWarningMessage("Please use the following to create a permanent account for you."); + args.Player.SendWarningMessage("{0}user add owner", Specifier); args.Player.SendInfoMessage("Creates: with the password as part of the owner group."); args.Player.SendInfoMessage("Please use {0}login after this process.", Specifier); - args.Player.SendInfoMessage("If you understand, please {0}login now, and then type {0}setup.", Specifier); + args.Player.SendWarningMessage("If you understand, please {0}login now, and then type {0}setup.", Specifier); return; } diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs index 5d30da0e..fb920732 100644 --- a/TShockAPI/ConfigFile.cs +++ b/TShockAPI/ConfigFile.cs @@ -441,12 +441,12 @@ namespace TShockAPI [Description("Whether or not to log REST API connections.")] public bool LogRest = false; - /// The number of seconds a player must wait before being respawned. - [Description("The number of seconds a player must wait before being respawned.")] + /// The number of seconds a player must wait before being respawned. Cannot be longer than normal value now. Use at your own risk. + [Description("The number of seconds a player must wait before being respawned. Cannot be longer than normal value now. Use at your own risk.")] public int RespawnSeconds = 5; - /// The number of seconds a player must wait before being respawned if there is a boss nearby. - [Description("The number of seconds a player must wait before being respawned if there is a boss nearby.")] + /// The number of seconds a player must wait before being respawned if there is a boss nearby. Cannot be longer than normal value now. Use at your own risk. + [Description("The number of seconds a player must wait before being respawned if there is a boss nearby. Cannot be longer than normal value now. Use at your own risk.")] public int RespawnBossSeconds = 10; /// Disables a player if this number of tiles is painted within 1 second. diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 93d79dea..19c6f4b0 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1129,10 +1129,21 @@ namespace TShockAPI /// public byte Amount { get; set; } /// - /// Type of Liquid: 0=water, 1=lave, 2=honey + /// Type of Liquid: 0=water, 1=lava, 2=honey /// - public byte Type { get; set; } + public LiquidType Type { get; set; } } + + /// + /// LiquidType - supported liquid types + /// + public enum LiquidType : byte + { + Water = 0, + Lava = 1, + Honey = 2 + } + /// /// LiquidSet - When ever a liquid is set /// @@ -1149,7 +1160,7 @@ namespace TShockAPI TileX = tilex, TileY = tiley, Amount = amount, - Type = type, + Type = (LiquidType) type, }; LiquidSet.Invoke(null, args); return args.Handled; @@ -1880,12 +1891,14 @@ namespace TShockAPI if (OnPlayerInfo(args.Player, args.Data, playerid, hair, skinVariant, difficulty, name)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerInfo rejected plugin phase {0}", name); args.Player.Kick("A plugin on this server stopped your login.", true, true); return true; } if (name.Trim().Length == 0) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerInfo rejected name length 0"); args.Player.Kick("You have been Bounced.", true, true); return true; } @@ -1914,11 +1927,13 @@ namespace TShockAPI } if (TShock.Config.MediumcoreOnly && difficulty < 1) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerInfo rejected mediumcore required"); args.Player.Kick("You need to join with a mediumcore player or higher.", true, true); return true; } if (TShock.Config.HardcoreOnly && difficulty < 2) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerInfo rejected hardcore required"); args.Player.Kick("You need to join with a hardcore player.", true, true); return true; } @@ -1950,6 +1965,7 @@ namespace TShockAPI return true; if (args.Player.IgnoreSSCPackets) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerSlot rejected ignore ssc packets"); args.Player.SendData(PacketTypes.PlayerSlot, "", args.Player.Index, slot, prefix); return true; } @@ -2055,6 +2071,7 @@ namespace TShockAPI if (TShock.Utils.GetActivePlayerCount() + 1 > TShock.Config.MaxSlots && !args.Player.HasPermission(Permissions.reservedslot)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleGetSection rejected reserve slot"); args.Player.Kick(TShock.Config.ServerFullReason, true, true); return true; } @@ -2065,6 +2082,12 @@ namespace TShockAPI private static bool HandleSpawn(GetDataHandlerArgs args) { + if (args.Player.Dead && args.Player.RespawnTimer > 0) + { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn rejected dead player spawn request {0}", args.Player.Name); + return true; + } + byte player = args.Data.ReadInt8(); short spawnx = args.Data.ReadInt16(); short spawny = args.Data.ReadInt16(); @@ -2074,6 +2097,14 @@ namespace TShockAPI if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, context)) return true; + if ((Main.ServerSideCharacter) && (spawnx == -1 && spawny == -1)) //this means they want to spawn to vanilla spawn + { + args.Player.sX = Main.spawnTileX; + args.Player.sY = Main.spawnTileY; + args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn force teleport 'vanilla spawn' {0}", args.Player.Name); + } + if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0) && (args.TPlayer.SpawnX > 0) && ((args.TPlayer.SpawnX != args.Player.sX) && (args.TPlayer.SpawnY != args.Player.sY))) { @@ -2081,13 +2112,19 @@ namespace TShockAPI args.Player.sY = args.TPlayer.SpawnY; if (((Main.tile[args.Player.sX, args.Player.sY - 1].active() && Main.tile[args.Player.sX, args.Player.sY - 1].type == 79)) && (WorldGen.StartRoomCheck(args.Player.sX, args.Player.sY - 1))) + { args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn force teleport phase 1 {0}", args.Player.Name); + } } else if ((Main.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0)) { if (((Main.tile[args.Player.sX, args.Player.sY - 1].active() && Main.tile[args.Player.sX, args.Player.sY - 1].type == 79)) && (WorldGen.StartRoomCheck(args.Player.sX, args.Player.sY - 1))) + { args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) - 48); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawn force teleport phase 2 {0}", args.Player.Name); + } } if (respawnTimer > 0) @@ -2123,6 +2160,7 @@ namespace TShockAPI { originalPosition = new Vector2?(args.Data.ReadVector2()); homePosition = new Vector2?(args.Data.ReadVector2()); + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerUpdate home position delta {0}", args.Player.Name); } if (OnPlayerUpdate(args.Player, args.Data, playerID, controls, miscData1, miscData2, miscData3, selectedItem, position, velocity, originalPosition, homePosition)) @@ -2142,6 +2180,7 @@ namespace TShockAPI if (max > TShock.Config.MaxHP && !args.Player.HasPermission(Permissions.ignorehp)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerHp rejected over max hp {0}", args.Player.Name); args.Player.Disable("Maximum HP beyond limit", DisableFlags.WriteToLogAndConsole); return true; } @@ -2190,11 +2229,13 @@ namespace TShockAPI if (x >= Main.maxTilesX || y >= Main.maxTilesY || x < 0 || y < 0) // Check for out of range { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleDoorUse rejected out of range door {0}", args.Player.Name); return true; } if (type < 0 || type > 5) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleDoorUse rejected type 0 5 check {0}", args.Player.Name); return true; } @@ -2204,6 +2245,7 @@ namespace TShockAPI && tileType != TileID.TallGateClosed && tileType != TileID.TallGateOpen && tileType != TileID.TrapdoorClosed && tileType != TileID.TrapdoorOpen) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleDoorUse rejected door gap check {0}", args.Player.Name); return true; } @@ -2298,6 +2340,7 @@ namespace TShockAPI { args.Player.SendErrorMessage("You do not have permission to hurt this NPC."); args.Player.SendData(PacketTypes.NpcUpdate, "", id); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleNpcStrike rejected npc strike {0}", args.Player.Name); return true; } @@ -2322,6 +2365,7 @@ namespace TShockAPI if (type == ProjectileID.Tombstone) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleProjectileKill rejected tombstone {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); return true; } @@ -2332,8 +2376,11 @@ namespace TShockAPI // https://github.com/Pryaxis/TShock/commit/a5aa9231239926f361b7246651e32144bbf28dda if (type == ProjectileID.Bomb || type == ProjectileID.DeathLaser) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleProjectileKill permitted skeletron prime exemption {0}", args.Player.Name); + TShock.Log.ConsoleDebug("If this was not skeletron prime related, please report to TShock what happened."); return false; } + TShock.Log.ConsoleDebug("GetDataHandlers / HandleProjectileKill rejected banned projectile {0}", args.Player.Name); args.Player.RemoveProjectile(ident, owner); return true; } @@ -2351,11 +2398,15 @@ namespace TShockAPI return true; if (id != args.Player.Index) + { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTogglePvp rejected index mismatch {0}", args.Player.Name); return true; + } string pvpMode = TShock.Config.PvPMode.ToLowerInvariant(); if (pvpMode == "disabled" || pvpMode == "always" || (DateTime.UtcNow - args.Player.LastPvPTeamChange).TotalSeconds < 5) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTogglePvp rejected fastswitch {0}", args.Player.Name); args.Player.SendData(PacketTypes.TogglePvp, "", id); return true; } @@ -2390,6 +2441,7 @@ namespace TShockAPI item.netDefaults(type); if (stacks > item.maxStack) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleChestItem rejected max stacks {0}", args.Player.Name); return true; } @@ -2414,6 +2466,7 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(x, y) && TShock.Config.RegionProtectChests) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleChestActive rejected build permission and region check {0}", args.Player.Name); args.Player.SendData(PacketTypes.ChestOpen, "", -1); return true; } @@ -2438,6 +2491,7 @@ namespace TShockAPI { if (args.Player == null || args.TPlayer == null || args.Data == null) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerZone rejected null check"); return true; } @@ -2548,6 +2602,7 @@ namespace TShockAPI if (max > TShock.Config.MaxMP && !args.Player.HasPermission(Permissions.ignoremp)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerMana rejected max mana {0} {1}/{2}", args.Player.Name, max, TShock.Config.MaxMP); args.Player.Disable("Maximum MP beyond limit", DisableFlags.WriteToLogAndConsole); return true; } @@ -2574,6 +2629,7 @@ namespace TShockAPI if ((DateTime.UtcNow - args.Player.LastPvPTeamChange).TotalSeconds < 5) { args.Player.SendData(PacketTypes.PlayerTeam, "", id); + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerTeam rejected team fastswitch {0}", args.Player.Name); return true; } @@ -2594,12 +2650,14 @@ namespace TShockAPI if (!args.Player.HasBuildPermission(x, y)) { args.Player.SendData(PacketTypes.SignNew, "", id); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSign rejected sign on build permission {0}", args.Player.Name); return true; } if (!args.Player.IsInRange(x, y)) { args.Player.SendData(PacketTypes.SignNew, "", id); + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSign rejected sign range check {0}", args.Player.Name); return true; } return false; @@ -2633,7 +2691,10 @@ namespace TShockAPI buff = 0; if (Netplay.Clients[args.TPlayer.whoAmI].State < 2 && (buff == 156 || buff == 47 || buff == 149)) + { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerBuffList zeroed player buff due to below state 2 {0} {1}", args.Player.Name, buff); buff = 0; + } args.TPlayer.buffType[i] = buff; if (args.TPlayer.buffType[i] > 0) @@ -2646,7 +2707,7 @@ namespace TShockAPI } } - + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerBuffList handled event and sent data {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.PlayerBuff, -1, args.Player.Index, NetworkText.Empty, args.Player.Index); return true; } @@ -2661,13 +2722,15 @@ namespace TShockAPI if (type == 1 && TShock.Config.DisableDungeonGuardian) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpecial rejected type 1 for {0}", args.Player.Name); args.Player.SendMessage("The Dungeon Guardian returned you to your spawn point", Color.Purple); args.Player.Spawn(PlayerSpawnContext.RecallFromItem); return true; } - if (type == 3 & !args.Player.HasPermission(Permissions.usesundial)) + if (type == 3 && !args.Player.HasPermission(Permissions.usesundial)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpecial rejected enchanted sundial permission {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to use the Enchanted Sundial!"); return true; } @@ -2712,6 +2775,7 @@ namespace TShockAPI if (!args.Player.HasPermission(Permissions.movenpc)) { + TShock.Log.ConsoleDebug("GetDataHandlers / UpdateNPCHome rejected no permission {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to relocate NPCs."); args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); @@ -2727,6 +2791,7 @@ namespace TShockAPI { if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawnBoss rejected bouner throttled {0}", args.Player.Name); return true; } @@ -2737,18 +2802,21 @@ namespace TShockAPI if (bosses.Contains(thingType) && !args.Player.HasPermission(Permissions.summonboss)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawnBoss rejected boss {0} {1}", args.Player.Name, thingType); args.Player.SendErrorMessage("You don't have permission to summon a boss."); return true; } if (invasions.Contains(thingType) && !args.Player.HasPermission(Permissions.startinvasion)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawnBoss rejected invasion {0} {1}", args.Player.Name, thingType); args.Player.SendErrorMessage("You don't have permission to start an invasion."); return true; } if (pets.Contains(thingType) && !args.Player.HasPermission(Permissions.spawnpets)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSpawnBoss rejected pet {0} {1}", args.Player.Name, thingType); args.Player.SendErrorMessage("You don't have permission to spawn pets."); return true; } @@ -2802,6 +2870,7 @@ namespace TShockAPI if (x < 0 || y < 0 || x >= Main.maxTilesX || y >= Main.maxTilesY || t > Main.numTileColors) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintTile rejected range check {0}", args.Player.Name); return true; } if (OnPaintTile(args.Player, args.Data, x, y, t)) @@ -2819,6 +2888,7 @@ namespace TShockAPI !args.Player.Accessories.Any(i => i != null && i.stack > 0 && (i.type == ItemID.PaintSprayer || i.type == ItemID.ArchitectGizmoPack))) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintTile rejected select consistency {0}", args.Player.Name); args.Player.SendData(PacketTypes.PaintTile, "", x, y, Main.tile[x, y].color()); return true; } @@ -2827,6 +2897,7 @@ namespace TShockAPI !args.Player.HasPaintPermission(x, y) || !args.Player.IsInRange(x, y)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintTile rejected throttle/permission/range check {0}", args.Player.Name); args.Player.SendData(PacketTypes.PaintTile, "", x, y, Main.tile[x, y].color()); return true; } @@ -2846,6 +2917,7 @@ namespace TShockAPI if (x < 0 || y < 0 || x >= Main.maxTilesX || y >= Main.maxTilesY || t > Main.numTileColors) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintWall rejected range check {0}", args.Player.Name); return true; } if (OnPaintWall(args.Player, args.Data, x, y, t)) @@ -2863,6 +2935,7 @@ namespace TShockAPI !args.Player.Accessories.Any(i => i != null && i.stack > 0 && (i.type == ItemID.PaintSprayer || i.type == ItemID.ArchitectGizmoPack))) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintWall rejected selector consistency {0}", args.Player.Name); args.Player.SendData(PacketTypes.PaintWall, "", x, y, Main.tile[x, y].wallColor()); return true; } @@ -2871,6 +2944,7 @@ namespace TShockAPI !args.Player.HasPaintPermission(x, y) || !args.Player.IsInRange(x, y)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePaintWall rejected throttle/permission/range {0}", args.Player.Name); args.Player.SendData(PacketTypes.PaintWall, "", x, y, Main.tile[x, y].wallColor()); return true; } @@ -2918,6 +2992,7 @@ namespace TShockAPI //Rod of Discord teleport (usually (may be used by modded clients to teleport)) if (type == 0 && !args.Player.HasPermission(Permissions.rod)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTeleport rejected rod type {0} {1}", args.Player.Name, type); args.Player.SendErrorMessage("You do not have permission to teleport."); args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y); return true; @@ -2926,6 +3001,7 @@ namespace TShockAPI //NPC teleport if (type == 1 && id >= Main.maxNPCs) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTeleport rejected npc teleport {0} {1}", args.Player.Name, type); return true; } @@ -2934,11 +3010,13 @@ namespace TShockAPI { if (id >= Main.maxPlayers || Main.player[id] == null || TShock.Players[id] == null) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTeleport rejected p2p extents {0} {1}", args.Player.Name, type); return true; } if (!args.Player.HasPermission(Permissions.wormhole)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleTeleport rejected p2p wormhole permission {0} {1}", args.Player.Name, type); args.Player.SendErrorMessage("You do not have permission to teleport."); args.Player.Teleport(args.TPlayer.position.X, args.TPlayer.position.Y); return true; @@ -2966,6 +3044,7 @@ namespace TShockAPI if (Main.npc[npcID]?.catchItem == 0) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleCatchNpc catch zero {0}", args.Player.Name); Main.npc[npcID].active = true; NetMessage.SendData((int)PacketTypes.NpcUpdate, -1, -1, NetworkText.Empty, npcID); return true; @@ -2984,6 +3063,7 @@ namespace TShockAPI private static bool HandleNumberOfAnglerQuestsCompleted(GetDataHandlerArgs args) { // Never sent by vanilla client, ignore this + TShock.Log.ConsoleDebug("GetDataHandlers / HandleNumberOfAnglerQuestsCompleted surprise packet! Someone tell the TShock team! {0}", args.Player.Name); return true; } @@ -3066,16 +3146,19 @@ namespace TShockAPI if (position.X < 0 || position.X >= Main.maxTilesX || position.Y < 0 || position.Y >= Main.maxTilesY) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSyncExtraValue rejected extents check {0}", args.Player.Name); return true; } if (!Main.expertMode) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSyncExtraValue rejected expert mode check {0}", args.Player.Name); return true; } if (!args.Player.IsInRange((int)position.X, (int)position.Y)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleSyncExtraValue rejected range check {0}", args.Player.Name); return true; } @@ -3092,6 +3175,7 @@ namespace TShockAPI { if (projectile.owner != args.TPlayer.whoAmI) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleKillPortal rejected owner mismatch check {0}", args.Player.Name); return true; } } @@ -3128,12 +3212,14 @@ namespace TShockAPI if (projectile == null || !projectile.active) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleNpcTeleportPortal rejected null check {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.NpcUpdate, -1, -1, NetworkText.Empty, npcIndex); return true; } if (projectile.type != ProjectileID.PortalGunGate) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleNpcTeleportPortal rejected not thinking with portals {0}", args.Player.Name); NetMessage.SendData((int)PacketTypes.NpcUpdate, -1, -1, NetworkText.Empty, npcIndex); return true; } @@ -3173,6 +3259,7 @@ namespace TShockAPI { if (args.Player != null && !args.Player.HasPermission(Permissions.toggleparty)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleToggleParty rejected no party {0}", args.Player.Name); args.Player.SendErrorMessage("You do not have permission to start a party."); return true; } @@ -3184,11 +3271,13 @@ namespace TShockAPI { if (args.Player.IsBouncerThrottled()) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleOldOnesArmy rejected throttled {0}", args.Player.Name); return true; } if (!args.Player.HasPermission(Permissions.startdd2)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandleOldOnesArmy rejected permissions {0}", args.Player.Name); args.Player.SendErrorMessage("You don't have permission to start the Old One's Army event."); return true; } @@ -3215,6 +3304,7 @@ namespace TShockAPI if (TShock.Players[id].GodMode) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerDamageV2 rejected (god mode on) {0}", args.Player.Name); TShock.Players[id].Heal(args.TPlayer.statLifeMax); } @@ -3258,10 +3348,14 @@ namespace TShockAPI if (shouldBan) { if (!args.Player.Ban(banReason, false, "TShock")) + { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerKillMeV2 kicked with difficulty {0} {1}", args.Player.Name, args.TPlayer.difficulty); args.Player.Kick("You died! Normally, you'd be banned.", true, true); + } } else if (shouldKick) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerKillMeV2 kicked with difficulty {0} {1}", args.Player.Name, args.TPlayer.difficulty); args.Player.Kick(kickReason, true, true, null, false); } } @@ -3270,6 +3364,7 @@ namespace TShockAPI { if (TShock.CharacterDB.RemovePlayer(args.Player.Account.ID)) { + TShock.Log.ConsoleDebug("GetDataHandlers / HandlePlayerKillMeV2 ssc delete {0} {1}", args.Player.Name, args.TPlayer.difficulty); args.Player.SendErrorMessage("You have fallen in hardcore mode, and your items have been lost forever."); TShock.CharacterDB.SeedInitialData(args.Player.Account); } @@ -3348,6 +3443,7 @@ namespace TShockAPI { ProjectileID.EbonsandBallGun, TileID.Ebonsand }, { ProjectileID.PearlSandBallGun, TileID.Pearlsand }, { ProjectileID.CrimsandBallGun, TileID.Crimsand }, + { ProjectileID.MysticSnakeCoil, TileID.MysticSnakeRope } }; internal static Dictionary ropeCoilPlacements = new Dictionary diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index f0c43aa0..95d9a39a 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -411,7 +411,7 @@ namespace TShockAPI var players = new ArrayList(); foreach (TSPlayer tsPlayer in TShock.Players.Where(p => null != p)) { - var p = PlayerFilter(tsPlayer, args.Parameters, ((args.TokenData.UserGroupName) != "" && TShock.Groups.GetGroupByName(args.TokenData.UserGroupName).HasPermission(RestPermissions.viewips))); + var p = PlayerFilter(tsPlayer, args.Parameters, (!string.IsNullOrEmpty(args.TokenData.UserGroupName) && TShock.Groups.GetGroupByName(args.TokenData.UserGroupName).HasPermission(RestPermissions.viewips))); if (null != p) players.Add(p); } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 8f450604..86642e69 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -299,9 +299,10 @@ namespace TShockAPI /// public int RespawnTimer { - get => TPlayer.respawnTimer; - set => TPlayer.respawnTimer = value; + get => _respawnTimer; + set => TPlayer.respawnTimer = (_respawnTimer = value) * 60; } + private int _respawnTimer; /// /// Whether the player is dead or not. @@ -600,8 +601,11 @@ namespace TShockAPI /// True if the player is in range of a tile or if range checks are off. False if not. public bool IsInRange(int x, int y, int range = 32) { - if (TShock.Config.RangeChecks && ((Math.Abs(TileX - x) > range) || (Math.Abs(TileY - y) > range))) + int rgX = Math.Abs(TileX - x); + int rgY = Math.Abs(TileY - y); + if (TShock.Config.RangeChecks && ((rgX > range) || (rgY > range))) { + TShock.Log.ConsoleDebug("Rangecheck failed for {0} ({1}, {2}) (rg: {3}/{5}, {4}/{5})", Name, x, y, rgX, rgY, range); return false; } return true; @@ -1196,7 +1200,7 @@ namespace TShockAPI PlayerIndex = (byte)Index, TileX = (short)tilex, TileY = (short)tiley, - RespawnTimer = respawnTimer ?? TShock.Players[Index].TPlayer.respawnTimer, + RespawnTimer = respawnTimer ?? TShock.Players[Index].RespawnTimer * 60, PlayerSpawnContext = context, }; msg.PackFull(ms); @@ -1420,7 +1424,15 @@ namespace TShockAPI } return; } - SendData(PacketTypes.SmartTextMessage, msg, 255, red, green, blue, -1); + + if (this.Index == -1) //-1 is our broadcast index - this implies we're using TSPlayer.All.SendMessage and broadcasting to all clients + { + Terraria.Chat.ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(msg), new Color(red, green, blue)); + } + else + { + Terraria.Chat.ChatHelper.SendChatMessageToClient(NetworkText.FromLiteral(msg), new Color(red, green, blue), this.Index); + } } /// @@ -1442,7 +1454,7 @@ namespace TShockAPI } return; } - SendDataFromPlayer(PacketTypes.SmartTextMessage, ply, msg, red, green, blue, -1); + Terraria.Chat.ChatHelper.BroadcastChatMessageAs((byte)ply, NetworkText.FromLiteral(msg), new Color(red, green, blue)); } /// diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index a8a164d0..d0b174b4 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -846,7 +846,7 @@ namespace TShockAPI if (File.Exists(Path.Combine(SavePath, "setup-code.txt"))) { - Log.ConsoleInfo("A superadmin account has been detected in the user database, but setup-code.txt is still present."); + Log.ConsoleInfo("An account has been detected in the user database, but setup-code.txt is still present."); Log.ConsoleInfo("TShock will now disable the initial setup system and remove setup-code.txt as it is no longer needed."); File.Delete(Path.Combine(SavePath, "setup-code.txt")); } diff --git a/TerrariaServerAPI b/TerrariaServerAPI index e39f6fe7..891380c8 160000 --- a/TerrariaServerAPI +++ b/TerrariaServerAPI @@ -1 +1 @@ -Subproject commit e39f6fe7526ddb6e67fe6c428e3614bae38d0c04 +Subproject commit 891380c8946dd53e670d34002d984e88d1c6179e