From 4c01740177afb64af2be438117d1d33db2a0f941 Mon Sep 17 00:00:00 2001 From: ohayo Date: Sun, 2 Feb 2025 12:08:14 +1000 Subject: [PATCH 01/15] Fix handshake stuff part 2 If the player has requested world data before sending the spawn player packet, they should be at state 3, otherwise they should be at state 1 for skipping it. Just check based on that instead. --- TShockAPI/GetDataHandlers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 8f70fd2c..42bd6401 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -2726,7 +2726,7 @@ namespace TShockAPI short numberOfDeathsPVP = args.Data.ReadInt16(); PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte(); - args.Player.FinishedHandshake = true; + args.Player.FinishedHandshake = args.Player.State == 3; //If the player has requested world data before sending spawn player, this should be set to 3, otherwise it'll be set to 1. if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context)) return true; From 4f2fff050dbbae17d59ff9fc9ddca677665010dd Mon Sep 17 00:00:00 2001 From: ohayo Date: Sun, 2 Feb 2025 12:40:04 +1000 Subject: [PATCH 02/15] Quick bug fix - forgot about respawns + only set handshake once The connection state should NEVER be set to under 3 if the player is fully connected. --- TShockAPI/GetDataHandlers.cs | 3 ++- TShockAPI/TShock.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 42bd6401..c0faf964 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -2726,7 +2726,8 @@ namespace TShockAPI short numberOfDeathsPVP = args.Data.ReadInt16(); PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte(); - args.Player.FinishedHandshake = args.Player.State == 3; //If the player has requested world data before sending spawn player, this should be set to 3, otherwise it'll be set to 1. + if (args.Player.State >= 3 && !args.Player.FinishedHandshake) + args.Player.FinishedHandshake = true; //If the player has requested world data before sending spawn player, this should be equal to or greater than 3, otherwise it'll usually be 1. Also only set this once to remove redundant updates. if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context)) return true; diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index e984da2f..d88b4403 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1461,7 +1461,8 @@ namespace TShockAPI } } - + TShock.Log.ConsoleInfo($"Setting handshake to false for {tsplr.Name}"); + tsplr.FinishedHandshake = false; // Fire the OnPlayerLogout hook too, if the player was logged in and they have a TSPlayer object. From b5d546a660907a6eda1bccb82395801a2315e021 Mon Sep 17 00:00:00 2001 From: ohayo Date: Sun, 2 Feb 2025 12:41:35 +1000 Subject: [PATCH 03/15] Remove debug logging (sorry haha) --- TShockAPI/TShock.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index d88b4403..061d05fa 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1461,8 +1461,6 @@ namespace TShockAPI } } - TShock.Log.ConsoleInfo($"Setting handshake to false for {tsplr.Name}"); - tsplr.FinishedHandshake = false; // Fire the OnPlayerLogout hook too, if the player was logged in and they have a TSPlayer object. From 52d1840003c82b83ae2654c4cf97f44a684cc72f Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 4 Feb 2025 11:07:10 +1000 Subject: [PATCH 04/15] Packet filtering for those who never finish the handshake This also kicks those who never finish handshaking upon chat now. (To free up the resources a bit I guess?) Before a player finishes the connection handshake, the server will check if it's necessary to send them a packet - it checks against a list of necessary packets like: - ContinueConnecting (Send User Slot), - PlayerSpawnSelf (CompleteConnectionAndSpawn), - WorldInfo (Which the server does a further check if the player is at the appropriate state to be sent the world info) - Status - Disconnection - TileFrameSection & TileSendSection --- TShockAPI/TSPlayer.cs | 28 ++++++++++++++++++++++++++++ TShockAPI/TShock.cs | 1 + 2 files changed, 29 insertions(+) diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index cb66649a..cb418b0e 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -2102,6 +2102,28 @@ namespace TShockAPI SendData(PacketTypes.PlayerAddBuff, number: Index, number2: type, number3: time); } + + /// + /// Determines if an outgoing packet is necessary to send to a player before they have finished the connection handshake. + /// + /// The packet type to check against the necessary list. + /// + private bool NecessaryPacket(PacketTypes msgType) + { + List ConnectionPackets = new List() + { + PacketTypes.ContinueConnecting, + PacketTypes.WorldInfo, + PacketTypes.Status, + PacketTypes.Disconnect, + PacketTypes.TileFrameSection, + PacketTypes.TileSendSection, + PacketTypes.PlayerSpawnSelf + }; + + return ConnectionPackets.Contains(msgType); + } + //Todo: Separate this into a few functions. SendTo, SendToAll, etc /// /// Sends data to the player. @@ -2119,6 +2141,12 @@ namespace TShockAPI if (RealPlayer && !ConnectionAlive) return; + if (!NecessaryPacket(msgType) && !FinishedHandshake) + return; + + if (msgType == PacketTypes.WorldInfo && State < 3) //If the player has requested the world data, their state will be 3. + return; + NetMessage.SendData((int)msgType, Index, -1, text == null ? null : NetworkText.FromLiteral(text), number, number2, number3, number4, number5); } diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 061d05fa..64f23ec3 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1494,6 +1494,7 @@ namespace TShockAPI if (!tsplr.FinishedHandshake) { + tsplr.Kick(GetString("Your client didn't finish the handshake."), true); args.Handled = true; return; } From fa3c1442741e291c17df08db93da3aa5422c6a82 Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 4 Feb 2025 11:28:09 +1000 Subject: [PATCH 05/15] Add necessary packets to a static hashset for further performance boosts title --- TShockAPI/TSPlayer.cs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index cb418b0e..6569ef01 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -2102,27 +2102,26 @@ namespace TShockAPI SendData(PacketTypes.PlayerAddBuff, number: Index, number2: type, number3: time); } + /// + /// The list of necessary packets to make sure gets through to the player upon connection (before they finish the handshake). + /// + private static readonly HashSet NecessaryPackets = new() + { + PacketTypes.ContinueConnecting, + PacketTypes.WorldInfo, + PacketTypes.Status, + PacketTypes.Disconnect, + PacketTypes.TileFrameSection, + PacketTypes.TileSendSection, + PacketTypes.PlayerSpawnSelf + }; /// /// Determines if an outgoing packet is necessary to send to a player before they have finished the connection handshake. /// /// The packet type to check against the necessary list. - /// - private bool NecessaryPacket(PacketTypes msgType) - { - List ConnectionPackets = new List() - { - PacketTypes.ContinueConnecting, - PacketTypes.WorldInfo, - PacketTypes.Status, - PacketTypes.Disconnect, - PacketTypes.TileFrameSection, - PacketTypes.TileSendSection, - PacketTypes.PlayerSpawnSelf - }; - - return ConnectionPackets.Contains(msgType); - } + /// Whether the packet is necessary for connection or not + private bool NecessaryPacket(PacketTypes msgType) => NecessaryPackets.Contains(msgType); //Todo: Separate this into a few functions. SendTo, SendToAll, etc /// From ff9cb9f8581b0cb4cbb6eb81afcbd2efbe75c5fb Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 4 Feb 2025 12:13:47 +1000 Subject: [PATCH 06/15] Change the cast PacketTypes for 74 to its corresponding definition --- TShockAPI/Commands.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index d82f10e2..f630165f 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -2530,8 +2530,8 @@ namespace TShockAPI { foreach (TSPlayer ply in TShock.Players.Where(p => p != null && p.Active && p.TPlayer.name.ToLower().Equals(args.Parameters[0].ToLower()))) { - //this will always tell the client that they have not done the quest today. - ply.SendData((PacketTypes)74, ""); + //this will always tell the client that they have not done the quest today. * Update: We have a definition for Packet 74, why are you sending it as a cast to PacketTypes? + ply.SendData(PacketTypes.AnglerQuest, ""); } args.Player.SendSuccessMessage(GetString("Removed {0} players from the angler quest completion list for today.", result)); } From ce04d9d173166f65d38c4956430b0f0379c76ea4 Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 4 Feb 2025 21:06:40 +1000 Subject: [PATCH 07/15] Remove magic number + Use suggestions by particles Added a new ClientState enum based on code in Terraria.MessageBuffer.GetData & Terraria.Netplay.InnerClientLoop --- TShockAPI/Commands.cs | 2 +- TShockAPI/DB/CharacterManager.cs | 2 +- TShockAPI/GetDataHandlers.cs | 25 +++++++++------- TShockAPI/TSPlayer.cs | 49 ++++++++++++++++++++++++++++++-- TShockAPI/TShock.cs | 6 ++-- 5 files changed, 66 insertions(+), 18 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index f630165f..f4d00f71 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -2530,7 +2530,7 @@ namespace TShockAPI { foreach (TSPlayer ply in TShock.Players.Where(p => p != null && p.Active && p.TPlayer.name.ToLower().Equals(args.Parameters[0].ToLower()))) { - //this will always tell the client that they have not done the quest today. * Update: We have a definition for Packet 74, why are you sending it as a cast to PacketTypes? + //this will always tell the client that they have not done the quest today. ply.SendData(PacketTypes.AnglerQuest, ""); } args.Player.SendSuccessMessage(GetString("Removed {0} players from the angler quest completion list for today.", result)); diff --git a/TShockAPI/DB/CharacterManager.cs b/TShockAPI/DB/CharacterManager.cs index 5a5e13a6..32ac924d 100644 --- a/TShockAPI/DB/CharacterManager.cs +++ b/TShockAPI/DB/CharacterManager.cs @@ -189,7 +189,7 @@ namespace TShockAPI.DB if (!player.IsLoggedIn) return false; - if (player.State < 10) + if (player.State < (int)ClientState.ClientSpawned) return false; if (player.HasPermission(Permissions.bypassssc) && !fromCommand) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index c0faf964..043b12a4 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -2618,7 +2618,7 @@ namespace TShockAPI private static bool HandleConnecting(GetDataHandlerArgs args) { - var account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name);// + var account = TShock.UserAccounts.GetUserAccountByName(args.Player.Name); args.Player.DataWhenJoined = new PlayerData(args.Player); args.Player.DataWhenJoined.CopyCharacter(args.Player); args.Player.PlayerData = new PlayerData(args.Player); @@ -2628,8 +2628,9 @@ namespace TShockAPI { if (account.UUID == args.Player.UUID) { - if (args.Player.State == 1) - args.Player.State = 2; + if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) + args.Player.State = (int)ClientState.ClientSentPlayerInformation; + NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); var group = TShock.Groups.GetGroupByName(account.Group); @@ -2687,8 +2688,9 @@ namespace TShockAPI return true; } - if (args.Player.State == 1) + if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) args.Player.State = 2; + NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); return true; } @@ -2726,8 +2728,8 @@ namespace TShockAPI short numberOfDeathsPVP = args.Data.ReadInt16(); PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte(); - if (args.Player.State >= 3 && !args.Player.FinishedHandshake) - args.Player.FinishedHandshake = true; //If the player has requested world data before sending spawn player, this should be equal to or greater than 3, otherwise it'll usually be 1. Also only set this once to remove redundant updates. + if (args.Player.State >= (int)ClientState.ClientRequestedWorldData && !args.Player.FinishedHandshake) + args.Player.FinishedHandshake = true; //If the player has requested world data before sending spawn player, they should be at the obvious ClientRequestedWorldData state. Also only set this once to remove redundant updates. if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context)) return true; @@ -3219,8 +3221,9 @@ namespace TShockAPI args.Player.RequiresPassword = false; args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID); - if (args.Player.State == 1) - args.Player.State = 2; + if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) + args.Player.State = (int)ClientState.ClientSentPlayerInformation; + NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); var group = TShock.Groups.GetGroupByName(account.Group); @@ -3267,8 +3270,10 @@ namespace TShockAPI if (TShock.Config.Settings.ServerPassword == password) { args.Player.RequiresPassword = false; - if (args.Player.State == 1) - args.Player.State = 2; + + if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) + args.Player.State = (int)ClientState.ClientSentPlayerInformation; + NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); return true; } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 6569ef01..aeadd408 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -62,6 +62,49 @@ namespace TShockAPI WriteToLogAndConsole } + /// + /// An enum based on the current client's connection state to the server. + /// + public enum ClientState : int + { + /// + /// The server has accepted the client's connection but now requires a password from them before they can continue. (Only for password protected servers) + /// + RequiresPassword = -1, + /// + /// The server has accepted the client's connection. In this state, they will send their current version string to the server. + /// + ClientConnecting = 0, + /// + /// The server has accepted the client's password to connect and/or the server has verified the client's version string as being correct. In this state, the server will send them their user slot and in return, they must send their player information. + /// + ClientReceivingPlayerSlot = 1, + /// + /// The client has sent their player information. In this state, they must request world data. + /// + ClientSentPlayerInformation = 2, + /// + /// The client has requested the world data. + /// + ClientRequestedWorldData = 3, + /// + /// The client has received the world data. + /// + ClientReceivedWorldData = 4, + /// + /// The client has loaded the world data and map. + /// + ClientLoadedWorldData = 5, + /// + /// The client is requesting tile data. + /// + ClientRequestingTileData = 6, + /// + /// The client has sent a SpawnPlayer packet and has finished the connection process. + /// + ClientSpawned = 10 + } + public class TSPlayer { /// @@ -2105,7 +2148,7 @@ namespace TShockAPI /// /// The list of necessary packets to make sure gets through to the player upon connection (before they finish the handshake). /// - private static readonly HashSet NecessaryPackets = new() + private static readonly HashSet HandshakeNecessaryPackets = new() { PacketTypes.ContinueConnecting, PacketTypes.WorldInfo, @@ -2121,7 +2164,7 @@ namespace TShockAPI /// /// The packet type to check against the necessary list. /// Whether the packet is necessary for connection or not - private bool NecessaryPacket(PacketTypes msgType) => NecessaryPackets.Contains(msgType); + private bool NecessaryPacket(PacketTypes msgType) => HandshakeNecessaryPackets.Contains(msgType); //Todo: Separate this into a few functions. SendTo, SendToAll, etc /// @@ -2143,7 +2186,7 @@ namespace TShockAPI if (!NecessaryPacket(msgType) && !FinishedHandshake) return; - if (msgType == PacketTypes.WorldInfo && State < 3) //If the player has requested the world data, their state will be 3. + if (msgType == PacketTypes.WorldInfo && State < (int)ClientState.ClientRequestedWorldData) return; NetMessage.SendData((int)msgType, Index, -1, text == null ? null : NetworkText.FromLiteral(text), number, number2, number3, number4, number5); diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 64f23ec3..6c1b251c 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1440,7 +1440,7 @@ namespace TShockAPI if (tsplr.ReceivedInfo) { - if (!tsplr.SilentKickInProgress && tsplr.State >= 3 && tsplr.FinishedHandshake) //The player has left, do not broadcast any clients exploiting the behaviour of not spawning their player. + if (!tsplr.SilentKickInProgress && tsplr.State >= (int)ClientState.ClientRequestedWorldData && tsplr.FinishedHandshake) //The player has left, do not broadcast any clients exploiting the behaviour of not spawning their player. Utils.Broadcast(GetString("{0} has left.", tsplr.Name), Color.Yellow); Log.Info(GetString("{0} disconnected.", tsplr.Name)); @@ -1494,7 +1494,7 @@ namespace TShockAPI if (!tsplr.FinishedHandshake) { - tsplr.Kick(GetString("Your client didn't finish the handshake."), true); + tsplr.Kick(GetString("Your didn't send the right connection information."), true); args.Handled = true; return; } @@ -1678,7 +1678,7 @@ namespace TShockAPI return; } - if ((player.State < 10 || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 && + if ((player.State < (int)ClientState.ClientSpawned || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 && (int)type != 38 && (int)type != 21 && (int)type != 22 && type != PacketTypes.SyncLoadout) { e.Handled = true; From 72f529fcb1f5a2de2aa0bdd5d857aa03f18bdafa Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 4 Feb 2025 21:24:44 +1000 Subject: [PATCH 08/15] Typo fix --- TShockAPI/TShock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 6c1b251c..b70a857d 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1494,7 +1494,7 @@ namespace TShockAPI if (!tsplr.FinishedHandshake) { - tsplr.Kick(GetString("Your didn't send the right connection information."), true); + tsplr.Kick(GetString("Your client didn't send the right connection information."), true); args.Handled = true; return; } From 5a23073db5834fd2bc7757a8ff5ff6f95fc1072c Mon Sep 17 00:00:00 2001 From: ohayo Date: Wed, 5 Feb 2025 09:33:36 +1000 Subject: [PATCH 09/15] Suggestions + fix last missed magic number --- TShockAPI/DB/CharacterManager.cs | 2 +- TShockAPI/GetDataHandlers.cs | 18 +++++++-------- TShockAPI/TSPlayer.cs | 38 ++++++++++++++++---------------- TShockAPI/TShock.cs | 4 ++-- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/TShockAPI/DB/CharacterManager.cs b/TShockAPI/DB/CharacterManager.cs index 32ac924d..0b8246b9 100644 --- a/TShockAPI/DB/CharacterManager.cs +++ b/TShockAPI/DB/CharacterManager.cs @@ -189,7 +189,7 @@ namespace TShockAPI.DB if (!player.IsLoggedIn) return false; - if (player.State < (int)ClientState.ClientSpawned) + if (player.State < (int)ConnectionState.Complete) return false; if (player.HasPermission(Permissions.bypassssc) && !fromCommand) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 043b12a4..ac290356 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -2628,8 +2628,8 @@ namespace TShockAPI { if (account.UUID == args.Player.UUID) { - if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) - args.Player.State = (int)ClientState.ClientSentPlayerInformation; + if (args.Player.State == (int)ConnectionState.AssigningPlayerSlot) + args.Player.State = (int)ConnectionState.AwaitingPlayerInfo; NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); @@ -2688,8 +2688,8 @@ namespace TShockAPI return true; } - if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) - args.Player.State = 2; + if (args.Player.State == (int)ConnectionState.AssigningPlayerSlot) + args.Player.State = (int)ConnectionState.AwaitingPlayerInfo; NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); return true; @@ -2728,7 +2728,7 @@ namespace TShockAPI short numberOfDeathsPVP = args.Data.ReadInt16(); PlayerSpawnContext context = (PlayerSpawnContext)args.Data.ReadByte(); - if (args.Player.State >= (int)ClientState.ClientRequestedWorldData && !args.Player.FinishedHandshake) + if (args.Player.State >= (int)ConnectionState.RequestingWorldData && !args.Player.FinishedHandshake) args.Player.FinishedHandshake = true; //If the player has requested world data before sending spawn player, they should be at the obvious ClientRequestedWorldData state. Also only set this once to remove redundant updates. if (OnPlayerSpawn(args.Player, args.Data, player, spawnx, spawny, respawnTimer, numberOfDeathsPVE, numberOfDeathsPVP, context)) @@ -3221,8 +3221,8 @@ namespace TShockAPI args.Player.RequiresPassword = false; args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID); - if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) - args.Player.State = (int)ClientState.ClientSentPlayerInformation; + if (args.Player.State == (int)ConnectionState.AssigningPlayerSlot) + args.Player.State = (int)ConnectionState.AwaitingPlayerInfo; NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); @@ -3271,8 +3271,8 @@ namespace TShockAPI { args.Player.RequiresPassword = false; - if (args.Player.State == (int)ClientState.ClientReceivingPlayerSlot) - args.Player.State = (int)ClientState.ClientSentPlayerInformation; + if (args.Player.State == (int)ConnectionState.AssigningPlayerSlot) + args.Player.State = (int)ConnectionState.AwaitingPlayerInfo; NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index); return true; diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index aeadd408..cf08d5bf 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -65,44 +65,44 @@ namespace TShockAPI /// /// An enum based on the current client's connection state to the server. /// - public enum ClientState : int + public enum ConnectionState : int { /// - /// The server has accepted the client's connection but now requires a password from them before they can continue. (Only for password protected servers) + /// The server is password protected and the connection is pending until a password is sent by the client. /// - RequiresPassword = -1, + AwaitingPassword = -1, /// - /// The server has accepted the client's connection. In this state, they will send their current version string to the server. + /// The connection has been established, and the client must verify its version. /// - ClientConnecting = 0, + AwaitingVersionCheck = 0, /// - /// The server has accepted the client's password to connect and/or the server has verified the client's version string as being correct. In this state, the server will send them their user slot and in return, they must send their player information. + /// The server has accepted the client's password to connect and/or the server has verified the client's version string as being correct. The client is now being assigned a player slot. /// - ClientReceivingPlayerSlot = 1, + AssigningPlayerSlot = 1, /// - /// The client has sent their player information. In this state, they must request world data. + /// The player slot has been received by the client, and the server is now waiting for the player information. /// - ClientSentPlayerInformation = 2, + AwaitingPlayerInfo = 2, /// - /// The client has requested the world data. + /// Player information has been received, and the client is requesting world data. /// - ClientRequestedWorldData = 3, + RequestingWorldData = 3, /// - /// The client has received the world data. + /// The world data is being sent to the client. /// - ClientReceivedWorldData = 4, + ReceivingWorldData = 4, /// - /// The client has loaded the world data and map. + /// The world data has been received, and the client is now finalizing the load. /// - ClientLoadedWorldData = 5, + FinalizingWorldLoad = 5, /// /// The client is requesting tile data. /// - ClientRequestingTileData = 6, + RequestingTileData = 6, /// - /// The client has sent a SpawnPlayer packet and has finished the connection process. + /// The connection process is complete (The player has spawned), and the client has fully joined the game. /// - ClientSpawned = 10 + Complete = 10 } public class TSPlayer @@ -2186,7 +2186,7 @@ namespace TShockAPI if (!NecessaryPacket(msgType) && !FinishedHandshake) return; - if (msgType == PacketTypes.WorldInfo && State < (int)ClientState.ClientRequestedWorldData) + if (msgType == PacketTypes.WorldInfo && State < (int)ConnectionState.RequestingWorldData) return; NetMessage.SendData((int)msgType, Index, -1, text == null ? null : NetworkText.FromLiteral(text), number, number2, number3, number4, number5); diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index b70a857d..f3afa716 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1440,7 +1440,7 @@ namespace TShockAPI if (tsplr.ReceivedInfo) { - if (!tsplr.SilentKickInProgress && tsplr.State >= (int)ClientState.ClientRequestedWorldData && tsplr.FinishedHandshake) //The player has left, do not broadcast any clients exploiting the behaviour of not spawning their player. + if (!tsplr.SilentKickInProgress && tsplr.State >= (int)ConnectionState.RequestingWorldData && tsplr.FinishedHandshake) //The player has left, do not broadcast any clients exploiting the behaviour of not spawning their player. Utils.Broadcast(GetString("{0} has left.", tsplr.Name), Color.Yellow); Log.Info(GetString("{0} disconnected.", tsplr.Name)); @@ -1678,7 +1678,7 @@ namespace TShockAPI return; } - if ((player.State < (int)ClientState.ClientSpawned || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 && + if ((player.State < (int)ConnectionState.Complete || player.Dead) && (int)type > 12 && (int)type != 16 && (int)type != 42 && (int)type != 50 && (int)type != 38 && (int)type != 21 && (int)type != 22 && type != PacketTypes.SyncLoadout) { e.Handled = true; From de142e419ea2544a30bbb705818751248fed5329 Mon Sep 17 00:00:00 2001 From: ohayo Date: Wed, 5 Feb 2025 09:37:53 +1000 Subject: [PATCH 10/15] I guess update the magic number here too? --- TShockAPI/GetDataHandlers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index ac290356..684d7f3e 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -3441,9 +3441,9 @@ namespace TShockAPI if (buff == 10 && TShock.Config.Settings.DisableInvisPvP && args.TPlayer.hostile) buff = 0; - if (Netplay.Clients[args.TPlayer.whoAmI].State < 2 && (buff == 156 || buff == 47 || buff == 149)) + if (Netplay.Clients[args.TPlayer.whoAmI].State < (int)ConnectionState.AwaitingPlayerInfo && (buff == 156 || buff == 47 || buff == 149)) { - TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandlePlayerBuffList zeroed player buff due to below state 2 {0} {1}", args.Player.Name, buff)); + TShock.Log.ConsoleDebug(GetString("GetDataHandlers / HandlePlayerBuffList zeroed player buff due to below state awaiting player information {0} {1}", args.Player.Name, buff)); buff = 0; } From 6d5fff83cf749a5b02d6f22c9262e5b602e17875 Mon Sep 17 00:00:00 2001 From: ohayo Date: Sat, 8 Feb 2025 14:37:48 +1000 Subject: [PATCH 11/15] Prevent blank UUIDs from being banned This fixes a bug with a bad actor getting banned with a blank client UUID and then preventing anyone from joining the server due to a lack of UUID on the Connect Request ban check. --- TShockAPI/Commands.cs | 2 +- TShockAPI/DB/BanManager.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index f4d00f71..16183431 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -1607,7 +1607,7 @@ namespace TShockAPI } } - if (banUuid) + if (banUuid && player.UUID.Length > 0) { banResult = DoBan($"{Identifier.UUID}{player.UUID}", reason, expiration); } diff --git a/TShockAPI/DB/BanManager.cs b/TShockAPI/DB/BanManager.cs index 42892100..3e93a3b7 100644 --- a/TShockAPI/DB/BanManager.cs +++ b/TShockAPI/DB/BanManager.cs @@ -189,11 +189,15 @@ namespace TShockAPI.DB { List identifiers = new List { - $"{Identifier.UUID}{player.UUID}", $"{Identifier.Name}{player.Name}", $"{Identifier.IP}{player.IP}" }; + if (player.UUID != null && player.UUID.Length > 0) + { + identifiers.Add($"{Identifier.UUID}{player.UUID}"); + } + if (player.Account != null) { identifiers.Add($"{Identifier.Account}{player.Account.Name}"); From 56c586504321d0cf5ff31ccd87e8ec51c75928fb Mon Sep 17 00:00:00 2001 From: ohayo Date: Tue, 11 Feb 2025 07:47:14 +1000 Subject: [PATCH 12/15] Emergency bug fix for handshake on all/server player The All Player does not have a valid state and because FinishedHandshake is false by default, they would never get time update packets, etc. --- TShockAPI/TSPlayer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index cf08d5bf..da9b7df6 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -35,6 +35,7 @@ using TShockAPI.Net; using Timer = System.Timers.Timer; using System.Linq; using Terraria.GameContent.Creative; +using SteelSeries.GameSense; namespace TShockAPI { @@ -1367,6 +1368,9 @@ namespace TShockAPI FakePlayer = new Player { name = playerName, whoAmI = -1 }; Group = Group.DefaultGroup; AwaitingResponse = new Dictionary>(); + + if (playerName == "All" || playerName == "Server") + FinishedHandshake = true; //Hot fix for the all player object not getting packets like TimeSet, etc because they have no state and finished handshake will always be false. } /// @@ -2186,7 +2190,7 @@ namespace TShockAPI if (!NecessaryPacket(msgType) && !FinishedHandshake) return; - if (msgType == PacketTypes.WorldInfo && State < (int)ConnectionState.RequestingWorldData) + if (FakePlayer != null && FakePlayer.whoAmI != -1 && msgType == PacketTypes.WorldInfo && State < (int)ConnectionState.RequestingWorldData) //So.. the All player doesn't have a state, so we cannot check this, skip over them if their index is -1 (server/all) return; NetMessage.SendData((int)msgType, Index, -1, text == null ? null : NetworkText.FromLiteral(text), number, number2, number3, number4, number5); From 98eed425e238cad814c85a754053b2f48b117a5c Mon Sep 17 00:00:00 2001 From: ohayo Date: Wed, 12 Feb 2025 21:51:14 +1000 Subject: [PATCH 13/15] Suppress logging of un-spawnable npcs Not anything related to the handshake fixes, but still a nice fix which could help server owners deal with mischievous client users. --- TShockAPI/GetDataHandlers.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 684d7f3e..1454299b 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -3648,10 +3648,15 @@ namespace TShockAPI thing = GetString("{0} summoned the {1}!", args.Player.Name, npc.FullName); break; } - if (TShock.Config.Settings.AnonymousBossInvasions) - TShock.Utils.SendLogs(thing, Color.PaleVioletRed, args.Player); - else - TShock.Utils.Broadcast(thing, 175, 75, 255); + + if (NPCID.Sets.MPAllowedEnemies[thingType]) + { + if (TShock.Config.Settings.AnonymousBossInvasions) + TShock.Utils.SendLogs(thing, Color.PaleVioletRed, args.Player); + else + TShock.Utils.Broadcast(thing, 175, 75, 255); + } + return false; } From 701a7d1ca0f1ad8d40f9d4342abf03ee353a8390 Mon Sep 17 00:00:00 2001 From: ohayo <9443476+ohayo@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:00:33 +1000 Subject: [PATCH 14/15] Update TShockAPI/TSPlayer.cs Co-authored-by: Chris <2648373+QuiCM@users.noreply.github.com> --- TShockAPI/TSPlayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index da9b7df6..2c70955b 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -35,7 +35,6 @@ using TShockAPI.Net; using Timer = System.Timers.Timer; using System.Linq; using Terraria.GameContent.Creative; -using SteelSeries.GameSense; namespace TShockAPI { From 1abb53b22e24aaed18c1e449ee987747e6743400 Mon Sep 17 00:00:00 2001 From: ohayo <9443476+ohayo@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:01:01 +1000 Subject: [PATCH 15/15] Update TShockAPI/TSPlayer.cs Oops Co-authored-by: Chris <2648373+QuiCM@users.noreply.github.com> --- TShockAPI/TSPlayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 2c70955b..3fb22887 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -35,7 +35,6 @@ using TShockAPI.Net; using Timer = System.Timers.Timer; using System.Linq; using Terraria.GameContent.Creative; - namespace TShockAPI { ///