From 7c8bf7712a78ae4876956e68a8e6ca35379bf4bf Mon Sep 17 00:00:00 2001 From: ProfessorXZ Date: Sun, 18 Dec 2016 12:35:18 +0100 Subject: [PATCH 01/17] Added TSPlayer.Logout() --- CHANGELOG.md | 5 ++++- TShockAPI/Commands.cs | 24 +----------------------- TShockAPI/TSPlayer.cs | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a433825a..9c71eee22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ 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 +* API: Version tick 2.0 +* API: Added TSPlayer.KillPlayer() (@WhiteXZ) +* API: Added TSPlayer.Logout() (@ProfessorXZ) +* Fixed connections after max slot is reached (@DeathCradle) ## TShock 4.3.21 * Compatibility with Terraria 1.3.4.3 (@Patrikkk, @Zaicon). @@ -26,7 +30,6 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Added `/uploadssc [player]` which allows someone to upload SSC data for [player] and store it on the server. Adds `tshock.ssc.upload` and `tshock.ssc.upload.others` permission nodes to match (@DogooFalchion). * Added hardened stone to the whitelist of tiles editable by players (@DogooFalchion). * Added conversion system to send convert old MOTD format into smart text, while preserving initial line starting values to keep byte optimization for background colors Thanks to (@WhiteXZ, @Simon311, and especially @DogooFalchion) for the hard work on this issue. -* Fixed server-sided inventory issues caused by bank3 (@ProfessorXZ) ## TShock 4.3.20 * Security improvement: The auth system is now automatically disabled if a superadmin exists in the database (@Enerdy). diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index f1a07d67d..a9f91a4df 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -892,29 +892,7 @@ private static void Logout(CommandArgs args) return; } - PlayerHooks.OnPlayerLogout(args.Player); - - - if (Main.ServerSideCharacter) - { - args.Player.IgnoreActionsForInventory = String.Format("Server side characters is enabled! Please {0}register or {0}login to play!", Commands.Specifier); - if (!args.Player.IgnoreActionsForClearingTrashCan && (!args.Player.Dead || args.Player.TPlayer.difficulty != 2)) - { - args.Player.PlayerData.CopyCharacter(args.Player); - TShock.CharacterDB.InsertPlayerData(args.Player); - } - } - - args.Player.PlayerData = new PlayerData(args.Player); - args.Player.Group = TShock.Groups.GetGroupByName(TShock.Config.DefaultGuestGroupName); - args.Player.tempGroup = null; - if (args.Player.tempGroupTimer != null) - { - args.Player.tempGroupTimer.Stop(); - } - args.Player.User = null; - args.Player.IsLoggedIn = false; - + args.Player.Logout(); args.Player.SendSuccessMessage("You have been successfully logged out of your account."); if (Main.ServerSideCharacter) { diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index cd64547fa..c6fb7093d 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -637,6 +637,33 @@ public object RemoveData(string key) return null; } + /// + /// Logs the player out of an account. + /// + public void Logout() + { + PlayerHooks.OnPlayerLogout(this); + if (Main.ServerSideCharacter) + { + IgnoreActionsForInventory = $"Server side characters is enabled! Please {Commands.Specifier}register or {Commands.Specifier}login to play!"; + if (!IgnoreActionsForClearingTrashCan && (!Dead || TPlayer.difficulty != 2)) + { + PlayerData.CopyCharacter(this); + TShock.CharacterDB.InsertPlayerData(this); + } + } + + PlayerData = new PlayerData(this); + Group = TShock.Groups.GetGroupByName(TShock.Config.DefaultGuestGroupName); + tempGroup = null; + if (tempGroupTimer != null) + { + tempGroupTimer.Stop(); + } + User = null; + IsLoggedIn = false; + } + /// /// Initializes a new instance of the class. /// From 84105aee294f4e4fea6995d44c89aade91140a56 Mon Sep 17 00:00:00 2001 From: ProfessorXZ Date: Sun, 18 Dec 2016 12:45:13 +0100 Subject: [PATCH 02/17] Update Changelog.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c71eee22..8d1943f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * API: Added TSPlayer.KillPlayer() (@WhiteXZ) * API: Added TSPlayer.Logout() (@ProfessorXZ) * Fixed connections after max slot is reached (@DeathCradle) +* Fixed server crashes caused by client disconnections when attempting to read closed sockets (@Enerdy) ## TShock 4.3.21 * Compatibility with Terraria 1.3.4.3 (@Patrikkk, @Zaicon). From 75f639ee472352242715ef3767d784b099bd9fa2 Mon Sep 17 00:00:00 2001 From: ProfessorXZ Date: Sun, 18 Dec 2016 13:30:16 +0100 Subject: [PATCH 03/17] Fixes #1347 --- TShockAPI/Commands.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index a9f91a4df..00374b610 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -1203,16 +1203,20 @@ private static void ViewAccountInfo(CommandArgs args) var user = TShock.Users.GetUserByName(username); if (user != null) { - DateTime LastSeen = DateTime.Parse(user.LastAccessed).ToLocalTime(); + DateTime LastSeen; string Timezone = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours.ToString("+#;-#"); - args.Player.SendSuccessMessage("{0}'s last login occured {1} {2} UTC{3}.", user.Name, LastSeen.ToShortDateString(), - LastSeen.ToShortTimeString(), Timezone); + if (DateTime.TryParse(user.LastAccessed, out LastSeen)) + { + LastSeen = DateTime.Parse(user.LastAccessed).ToLocalTime(); + args.Player.SendSuccessMessage("{0}'s last login occured {1} {2} UTC{3}.", user.Name, LastSeen.ToShortDateString(), + LastSeen.ToShortTimeString(), Timezone); + } if (args.Player.Group.HasPermission(Permissions.advaccountinfo)) { - List KnownIps = JsonConvert.DeserializeObject>(user.KnownIps); - string ip = KnownIps[KnownIps.Count - 1]; + List KnownIps = JsonConvert.DeserializeObject>(user.KnownIps?.ToString() ?? string.Empty); + string ip = KnownIps?[KnownIps.Count - 1] ?? "N/A"; DateTime Registered = DateTime.Parse(user.Registered).ToLocalTime(); args.Player.SendSuccessMessage("{0}'s group is {1}.", user.Name, user.Group); From 9c150e6ce184fafc2de1f6851ac89ee778ecf603 Mon Sep 17 00:00:00 2001 From: Lucas Nicodemus Date: Sun, 18 Dec 2016 14:15:43 -0700 Subject: [PATCH 04/17] Test commit From 2236a5bb56005716663d16b54c7d5e7e5de78bda Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Wed, 21 Dec 2016 20:39:27 -0500 Subject: [PATCH 05/17] More SSC cleanup. Fixes prefix issues. --- TShockAPI/NetItem.cs | 8 ++++- TShockAPI/PlayerData.cs | 78 +++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/TShockAPI/NetItem.cs b/TShockAPI/NetItem.cs index 8d6b4e2a1..b11b3fba3 100644 --- a/TShockAPI/NetItem.cs +++ b/TShockAPI/NetItem.cs @@ -71,6 +71,11 @@ public struct NetItem /// public static readonly int MiscDyeSlots = MiscEquipSlots; + /// + /// 1 - The number of trash can slots. + /// + public static readonly int TrashSlots = 1; + /// /// 180 - The inventory size (inventory, held item, armour, dies, coins, ammo, piggy, safe, and trash) /// @@ -83,7 +88,8 @@ public struct NetItem public static readonly Tuple MiscDyeIndex = new Tuple(MiscEquipIndex.Item2, MiscEquipIndex.Item2 + MiscDyeSlots); public static readonly Tuple PiggyIndex = new Tuple(MiscDyeIndex.Item2, MiscDyeIndex.Item2 + PiggySlots); public static readonly Tuple SafeIndex = new Tuple(PiggyIndex.Item2, PiggyIndex.Item2 + SafeSlots); - public static readonly Tuple ForgeIndex = new Tuple(SafeIndex.Item2, SafeIndex.Item2 + ForgeSlots); + public static readonly Tuple TrashIndex = new Tuple(SafeIndex.Item2, SafeIndex.Item2 + TrashSlots); + public static readonly Tuple ForgeIndex = new Tuple(TrashIndex.Item2, TrashIndex.Item2 + ForgeSlots); [JsonProperty("netID")] private int _netId; diff --git a/TShockAPI/PlayerData.cs b/TShockAPI/PlayerData.cs index 9cd7c97b9..44711bada 100644 --- a/TShockAPI/PlayerData.cs +++ b/TShockAPI/PlayerData.cs @@ -164,16 +164,17 @@ public void CopyCharacter(TSPlayer player) var index = i - NetItem.SafeIndex.Item1; this.inventory[i] = (NetItem)safe[index]; } - else if (i < NetItem.ForgeIndex.Item2) + else if (i < NetItem.TrashIndex.Item2) { //179-219 - var index = i - NetItem.ForgeIndex.Item1; - this.inventory[i] = (NetItem)forge[index]; + this.inventory[i] = (NetItem)trash; } else { //220 - this.inventory[i] = (NetItem)trash; + var index = i - NetItem.ForgeIndex.Item1; + this.inventory[i] = (NetItem)forge[index]; + } } } @@ -226,7 +227,7 @@ public void RestoreCharacter(TSPlayer player) for (int i = 0; i < NetItem.MaxInventory; i++) { - if (i < NetItem.InventorySlots) + if (i < NetItem.InventoryIndex.Item2) { //0-58 player.TPlayer.inventory[i].netDefaults(this.inventory[i].NetId); @@ -237,10 +238,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.inventory[i].prefix = this.inventory[i].PrefixId; } } - else if (i < NetItem.InventorySlots + NetItem.ArmorSlots) + else if (i < NetItem.ArmorIndex.Item2) { //59-78 - var index = i - NetItem.InventorySlots; + var index = i - NetItem.ArmorIndex.Item1; player.TPlayer.armor[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.armor[index].netID != 0) @@ -249,10 +250,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.armor[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots) + else if (i < NetItem.DyeIndex.Item2) { //79-88 - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots); + var index = i - NetItem.DyeIndex.Item1; player.TPlayer.dye[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.dye[index].netID != 0) @@ -261,11 +262,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.dye[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots) + else if (i < NetItem.MiscEquipIndex.Item2) { //89-93 - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots); + var index = i - NetItem.MiscEquipIndex.Item1; player.TPlayer.miscEquips[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.miscEquips[index].netID != 0) @@ -274,13 +274,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.miscEquips[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots - + NetItem.MiscDyeSlots) + else if (i < NetItem.MiscDyeIndex.Item2) { //93-98 - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots); + var index = i - NetItem.MiscDyeIndex.Item1; player.TPlayer.miscDyes[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.miscDyes[index].netID != 0) @@ -289,13 +286,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.miscDyes[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots) + else if (i < NetItem.PiggyIndex.Item2) { //98-138 - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots); + var index = i - NetItem.PiggyIndex.Item1; player.TPlayer.bank.item[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.bank.item[index].netID != 0) @@ -304,12 +298,10 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.bank.item[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots) + else if (i < NetItem.SafeIndex.Item2) { - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots); + //138-178 + var index = i - NetItem.SafeIndex.Item1; player.TPlayer.bank2.item[index].netDefaults(this.inventory[i].NetId); if (player.TPlayer.bank2.item[index].netID != 0) @@ -318,29 +310,30 @@ public void RestoreCharacter(TSPlayer player) player.TPlayer.bank2.item[index].prefix = (byte)this.inventory[i].PrefixId; } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots + NetItem.ForgeSlots) + else if (i < NetItem.TrashIndex.Item2) { - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots); - player.TPlayer.bank3.item[index].netDefaults(this.inventory[i].NetId); + //179-219 + var index = i - NetItem.TrashIndex.Item1; + player.TPlayer.trashItem.netDefaults(this.inventory[i].NetId); - if (player.TPlayer.bank3.item[index].netID != 0) + if (player.TPlayer.trashItem.netID != 0) { - player.TPlayer.bank3.item[index].stack = this.inventory[i].Stack; - player.TPlayer.bank3.item[index].prefix = (byte)this.inventory[i].PrefixId; + player.TPlayer.trashItem.stack = this.inventory[i].Stack; + player.TPlayer.trashItem.prefix = (byte)this.inventory[i].PrefixId; } } else { - player.TPlayer.trashItem.netDefaults(this.inventory[i].NetId); + //220 + var index = i - NetItem.ForgeIndex.Item1; + player.TPlayer.bank3.item[index].netDefaults(this.inventory[i].NetId); - if (player.TPlayer.trashItem.netID != 0) + if (player.TPlayer.bank3.item[index].netID != 0) { - player.TPlayer.trashItem.stack = this.inventory[i].Stack; - player.TPlayer.trashItem.prefix = (byte)this.inventory[i].PrefixId; + player.TPlayer.bank3.item[index].stack = this.inventory[i].Stack; + player.TPlayer.bank3.item[index].Prefix((byte)this.inventory[i].PrefixId); } + } } @@ -380,13 +373,13 @@ public void RestoreCharacter(TSPlayer player) NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix); slot++; } + NetMessage.SendData(5, -1, -1, Main.player[player.Index].trashItem.name, player.Index, slot++, (float)Main.player[player.Index].trashItem.prefix); for (int k = 0; k < NetItem.ForgeSlots; k++) { NetMessage.SendData(5, -1, -1, Main.player[player.Index].bank3.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank3.item[k].prefix); slot++; } - NetMessage.SendData(5, -1, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix); NetMessage.SendData(4, -1, -1, player.Name, player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(42, -1, -1, "", player.Index, 0f, 0f, 0f, 0); @@ -428,13 +421,14 @@ public void RestoreCharacter(TSPlayer player) NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank2.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank2.item[k].prefix); slot++; } + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].trashItem.name, player.Index, slot++, (float)Main.player[player.Index].trashItem.prefix); for (int k = 0; k < NetItem.ForgeSlots; k++) { NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].bank3.item[k].name, player.Index, slot, (float)Main.player[player.Index].bank3.item[k].prefix); slot++; } - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].trashItem.name, player.Index, slot, (float)Main.player[player.Index].trashItem.prefix); + NetMessage.SendData(4, player.Index, -1, player.Name, player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(42, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0); From 95c5129fa9ad309e5367ad2abf19c01c28f2d285 Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Wed, 21 Dec 2016 20:43:09 -0500 Subject: [PATCH 06/17] More SSC cleanup. --- TShockAPI/TShock.cs | 67 +++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 493ec01a0..c13bcff26 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1951,6 +1951,7 @@ public static float Distance(Vector2 value1, Vector2 value2) /// bool - True if the player has a hacked inventory. public static bool HackedInventory(TSPlayer player) { + //TODO: Update this to the new logic in PlayerData. bool check = false; Item[] inventory = player.TPlayer.inventory; @@ -1962,10 +1963,9 @@ public static bool HackedInventory(TSPlayer player) Item[] safe = player.TPlayer.bank2.item; Item[] forge = player.TPlayer.bank3.item; Item trash = player.TPlayer.trashItem; - for (int i = 0; i < NetItem.MaxInventory; i++) { - if (i < NetItem.InventorySlots) + if (i < NetItem.InventoryIndex.Item2) { //0-58 Item item = new Item(); @@ -1983,11 +1983,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < NetItem.InventorySlots + NetItem.ArmorSlots) + else if (i < NetItem.ArmorIndex.Item2) { //59-78 + var index = i - NetItem.ArmorIndex.Item1; Item item = new Item(); - var index = i - NetItem.InventorySlots; if (armor[index] != null && armor[index].netID != 0) { item.netDefaults(armor[index].netID); @@ -2002,11 +2002,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots) + else if (i < NetItem.DyeIndex.Item2) { //79-88 + var index = i - NetItem.DyeIndex.Item1; Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots); if (dye[index] != null && dye[index].netID != 0) { item.netDefaults(dye[index].netID); @@ -2021,12 +2021,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots) + else if (i < NetItem.MiscEquipIndex.Item2) { //89-93 + var index = i - NetItem.MiscEquipIndex.Item1; Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots); if (miscEquips[index] != null && miscEquips[index].netID != 0) { item.netDefaults(miscEquips[index].netID); @@ -2041,14 +2040,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots - + NetItem.MiscDyeSlots) + else if (i < NetItem.MiscDyeIndex.Item2) { //93-98 + var index = i - NetItem.MiscDyeIndex.Item1; Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots); if (miscDyes[index] != null && miscDyes[index].netID != 0) { item.netDefaults(miscDyes[index].netID); @@ -2063,14 +2059,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots) + else if (i < NetItem.PiggyIndex.Item2) { //98-138 + var index = i - NetItem.PiggyIndex.Item1; Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots); if (piggy[index] != null && piggy[index].netID != 0) { item.netDefaults(piggy[index].netID); @@ -2086,14 +2079,11 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots) + else if (i < NetItem.SafeIndex.Item2) { //138-178 + var index = i - NetItem.SafeIndex.Item1; Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots); if (safe[index] != null && safe[index].netID != 0) { item.netDefaults(safe[index].netID); @@ -2109,46 +2099,45 @@ public static bool HackedInventory(TSPlayer player) } } } - else if (i < - NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots + NetItem.MiscEquipSlots + - NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots + NetItem.ForgeSlots) + else if (i < NetItem.TrashIndex.Item2) { //179-219 Item item = new Item(); - var index = i - (NetItem.InventorySlots + NetItem.ArmorSlots + NetItem.DyeSlots - + NetItem.MiscEquipSlots + NetItem.MiscDyeSlots + NetItem.PiggySlots + NetItem.SafeSlots); - if (forge[index] != null && forge[index].netID != 0) + if (trash != null && trash.netID != 0) { - item.netDefaults(forge[index].netID); - item.Prefix(forge[index].prefix); + item.netDefaults(trash.netID); + item.Prefix(trash.prefix); item.AffixName(); - if (forge[index].stack > item.maxStack) + if (trash.stack > item.maxStack) { check = true; player.SendMessage( - String.Format("Stack cheat detected. Remove Defender's Forge item {0} ({1}) and then rejoin", item.name, forge[index].stack), + String.Format("Stack cheat detected. Remove trash item {0} ({1}) and then rejoin", item.name, trash.stack), Color.Cyan); } } } else { + //220 + var index = i - NetItem.ForgeIndex.Item1; Item item = new Item(); - if (trash != null && trash.netID != 0) + if (forge[index] != null && forge[index].netID != 0) { - item.netDefaults(trash.netID); - item.Prefix(trash.prefix); + item.netDefaults(forge[index].netID); + item.Prefix(forge[index].prefix); item.AffixName(); - if (trash.stack > item.maxStack) + if (forge[index].stack > item.maxStack) { check = true; player.SendMessage( - String.Format("Stack cheat detected. Remove trash item {0} ({1}) and then rejoin", item.name, trash.stack), + String.Format("Stack cheat detected. Remove Defender's Forge item {0} ({1}) and then rejoin", item.name, forge[index].stack), Color.Cyan); } } + } } From 84a84bdf05b7e0f61eb54b547895113743d0642b Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Wed, 21 Dec 2016 20:44:42 -0500 Subject: [PATCH 07/17] Remove todo reminder. --- TShockAPI/TShock.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index c13bcff26..fcd30a653 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1951,7 +1951,6 @@ public static float Distance(Vector2 value1, Vector2 value2) /// bool - True if the player has a hacked inventory. public static bool HackedInventory(TSPlayer player) { - //TODO: Update this to the new logic in PlayerData. bool check = false; Item[] inventory = player.TPlayer.inventory; From 0a1e831fba4d1ff7c6df9b8a45c90b0d301d4481 Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Wed, 21 Dec 2016 21:16:00 -0500 Subject: [PATCH 08/17] Add rope coils and the ropes they place to the tile create exceptions. Fixes #1352 --- TShockAPI/GetDataHandlers.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index cead709a0..0a11d8983 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1940,6 +1940,14 @@ public enum EditType { ProjectileID.CrimsandBallGun, TileID.Crimsand }, }; + private static Dictionary ropeCoilPlacements = new Dictionary + { + {ItemID.RopeCoil, TileID.Rope}, + {ItemID.SilkRopeCoil, TileID.SilkRope}, + {ItemID.VineRopeCoil, TileID.VineRope}, + {ItemID.WebRopeCoil, TileID.WebRope} + }; + /// /// Extra place style limits for strange hardcoded values in Terraria /// @@ -2115,7 +2123,8 @@ private static bool HandleTile(GetDataHandlerArgs args) // If they aren't selecting the item which creates the tile or wall, they're hacking. if (!(selectedItem.netID == ItemID.IceRod && editData == TileID.MagicalIceBlock) && - editData != (action == EditAction.PlaceTile ? selectedItem.createTile : selectedItem.createWall)) + (editData != (action == EditAction.PlaceTile ? selectedItem.createTile : selectedItem.createWall) && + !(ropeCoilPlacements.ContainsKey(selectedItem.netID) && editData == ropeCoilPlacements[selectedItem.netID]))) { args.Player.SendTileSquare(tileX, tileY, 4); return true; From 4459a97fdf3c8fa3605cca65024cac3f9868e081 Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Thu, 29 Dec 2016 18:08:36 -0500 Subject: [PATCH 09/17] Document and fix the fishing quest count glitch in SSC. --- TShockAPI/PlayerData.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TShockAPI/PlayerData.cs b/TShockAPI/PlayerData.cs index 44711bada..cc82cab63 100644 --- a/TShockAPI/PlayerData.cs +++ b/TShockAPI/PlayerData.cs @@ -438,8 +438,17 @@ public void RestoreCharacter(TSPlayer player) { player.TPlayer.buffType[k] = 0; } + + /* + * The following packets are sent twice because the server will not send a packet to a client + * if they have not spawned yet if the remoteclient is -1 + * This is for when players login via uuid or serverpassword instead of via + * the login command. + */ NetMessage.SendData(50, -1, -1, "", player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(50, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0); + + NetMessage.SendData(76, player.Index, -1, "", player.Index); NetMessage.SendData(76, -1, -1, "", player.Index); NetMessage.SendData(39, player.Index, -1, "", 400); From 3075708c967ff37ceffa147d0c07572fce817db4 Mon Sep 17 00:00:00 2001 From: DogooFalchion Date: Thu, 29 Dec 2016 21:51:58 -0500 Subject: [PATCH 10/17] Fix for trap doors. Also add in protection in the tile conversion logic to not needless trigger sendtilesquare. Remove existing trapdoor bypass. --- TShockAPI/GetDataHandlers.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 0a11d8983..2c9d77b3c 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1719,15 +1719,7 @@ private static bool HandleSendTileSquare(GetDataHandlerArgs args) var tileX = args.Data.ReadInt16(); var tileY = args.Data.ReadInt16(); - bool isTrapdoor = false; - - if (Main.tile[tileX, tileY].type == TileID.TrapdoorClosed - || Main.tile[tileX, tileY].type == TileID.TrapdoorOpen) - { - isTrapdoor = true; - } - - if (args.Player.HasPermission(Permissions.allowclientsideworldedit) && !isTrapdoor) + if (args.Player.HasPermission(Permissions.allowclientsideworldedit)) return false; if (OnSendTileSquare(size, tileX, tileY)) @@ -1826,7 +1818,7 @@ private static bool HandleSendTileSquare(GetDataHandlerArgs args) changed = true; } - if (tile.active() && newtile.Active) + if (tile.active() && newtile.Active && tile.type != newtile.Type) { // Grass <-> Grass if ((TileID.Sets.Conversion.Grass[tile.type] && TileID.Sets.Conversion.Grass[newtile.Type]) || @@ -1859,6 +1851,17 @@ private static bool HandleSendTileSquare(GetDataHandlerArgs args) Main.tile[realx, realy].wall = newtile.Wall; changed = true; } + + if ((tile.type == TileID.TrapdoorClosed && (newtile.Type == TileID.TrapdoorOpen || !newtile.Active)) || + (tile.type == TileID.TrapdoorOpen && (newtile.Type == TileID.TrapdoorClosed || !newtile.Active)) || + (!tile.active() && newtile.Active && (newtile.Type == TileID.TrapdoorOpen||newtile.Type == TileID.TrapdoorClosed))) + { + Main.tile[realx, realy].type = newtile.Type; + Main.tile[realx, realy].frameX = newtile.FrameX; + Main.tile[realx, realy].frameY = newtile.FrameY; + Main.tile[realx, realy].active(newtile.Active); + changed = true; + } } } From 36904b673f819f4a7b26727031cdc963f9901c78 Mon Sep 17 00:00:00 2001 From: White Date: Sat, 31 Dec 2016 11:30:32 +1030 Subject: [PATCH 11/17] Submodule update --- TerrariaServerAPI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TerrariaServerAPI b/TerrariaServerAPI index 302124e1b..ecb3b742b 160000 --- a/TerrariaServerAPI +++ b/TerrariaServerAPI @@ -1 +1 @@ -Subproject commit 302124e1bcf6a6661d518b84f630384a90dbcbcb +Subproject commit ecb3b742b795fb489f9fb6f8ee1c17667f64f85a From 4f7a15f9bf9def857ef9b0ce8c8b46e13fe68af3 Mon Sep 17 00:00:00 2001 From: White Date: Sat, 31 Dec 2016 11:33:48 +1030 Subject: [PATCH 12/17] Ensures Netplay.ServerPassword is always empty. This prevents an issue in which packets are sent in an unexpected order resulting in clients being unable to connect when a CLI-defined password is used. A CLI-defined password will now override any TShock config-defined password. --- TShockAPI/TShock.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index fcd30a653..1efab2a38 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -822,6 +822,7 @@ public static void HandleCommandLinePostConfigLoad(string[] parms) /// AuthToken - The auth token used by the /auth system to grant temporary superadmin access to new admins. public static int AuthToken = -1; + private string _cliPassword = null; /// OnPostInit - Fired when the server loads a map, to perform world specific operations. /// args - The EventArgs object. @@ -829,6 +830,16 @@ private void OnPostInit(EventArgs args) { SetConsoleTitle(false); + //This is to prevent a bug where a CLI-defined password causes packets to be + //sent in an unexpected order, resulting in clients being unable to connect + if (!string.IsNullOrEmpty(Netplay.ServerPassword)) + { + //CLI defined password overrides a config password + _cliPassword = Netplay.ServerPassword; + Netplay.ServerPassword = ""; + Config.ServerPassword = _cliPassword; + } + // Disable the auth system if "auth.lck" is present or a superadmin exists if (File.Exists(Path.Combine(SavePath, "auth.lck")) || Users.GetUsers().Exists(u => u.Group == new SuperAdminGroup().Name)) { @@ -2172,7 +2183,14 @@ public void OnConfigRead(ConfigFile file) if (file.MaxSlots > 235) file.MaxSlots = 235; Main.maxNetPlayers = file.MaxSlots + 20; + Netplay.ServerPassword = ""; + if (!string.IsNullOrEmpty(_cliPassword)) + { + //This prevents a config reload from removing/updating a CLI-defined password + file.ServerPassword = _cliPassword; + } + Netplay.spamCheck = false; } } From 24da3890505f82f0e821036859547ed88092e4c0 Mon Sep 17 00:00:00 2001 From: White Date: Sat, 31 Dec 2016 11:55:10 +1030 Subject: [PATCH 13/17] Re-added `/status` and added mute bool to `/v3/players/read`. `/status` is now a root endpoint and will always point to `/v2/server/status` with an added `upgrade` field describing the route to the latest status endpoint. Closes #1358. Closes #1348 --- TShockAPI/Rest/RestManager.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index b62fc9dd3..20e0ddb25 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License using System.IO; using System.Linq; using System.Reflection; -using System.Reflection.Emit; using System.Text; using HttpServer; using Rests; @@ -102,12 +101,14 @@ public void RegisterRestfulCommands() // Server Commands if (TShock.Config.EnableTokenEndpointAuthentication) { + Rest.Register(new SecureRestCommand("/status", ServerStatusRoot)); Rest.Register(new SecureRestCommand("/v2/server/status", ServerStatusV2)); Rest.Register(new SecureRestCommand("/v3/server/motd", ServerMotd)); Rest.Register(new SecureRestCommand("/v3/server/rules", ServerRules)); } else { + Rest.Register(new RestCommand("/status", (a) => this.ServerStatusRoot(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context)))); Rest.Register(new RestCommand("/v2/server/status", (a) => this.ServerStatusV2(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context)))); Rest.Register(new RestCommand("/v3/server/motd", (a) => this.ServerMotd(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context)))); Rest.Register(new RestCommand("/v3/server/rules", (a) => this.ServerRules(new RestRequestArgs(a.Verbs, a.Parameters, a.Request, SecureRest.TokenData.None, a.Context)))); @@ -274,6 +275,16 @@ private object ServerRules(RestRequestArgs args) }; } + [Description("Get a list of information about the current TShock server.")] + [Route("/status")] + [Token] + private object ServerStatusRoot(RestRequestArgs args) + { + RestObject status = (RestObject)ServerStatusV2(args); + status.Add("upgrade", "/v2/server/status"); + return status; + } + [Description("Get a list of information about the current TShock server.")] [Route("/v2/server/status")] [Token] @@ -761,10 +772,11 @@ private object PlayerReadV3(RestRequestArgs args) return new RestObject() { {"nickname", player.Name}, - {"username", null == player.User ? "" : player.User.Name}, + {"username", player.User?.Name}, {"ip", player.IP}, {"group", player.Group.Name}, - {"registered", null == player.User ? "" : player.User.Registered}, + {"registered", player.User?.Registered}, + {"muted", player.mute }, {"position", player.TileX + "," + player.TileY}, {"inventory", string.Join(", ", inventory.Select(p => (p.name + ":" + p.stack)))}, {"armor", string.Join(", ", equipment.Select(p => (p.netID + ":" + p.prefix)))}, From 6359dad213365820da984708328e2b96d8588281 Mon Sep 17 00:00:00 2001 From: White Date: Sat, 31 Dec 2016 12:57:16 +1030 Subject: [PATCH 14/17] AllowCutTilesAndBreakables option works better now. Herbs, vines, flowers can be cut inside regions if the option is enabled. Any action that would also break a wall is still ignored. Closes #1334 --- TShockAPI/GetDataHandlers.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 0a11d8983..af9507fe5 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -2200,8 +2200,13 @@ private static bool HandleTile(GetDataHandlerArgs args) return true; } } - if (TShock.Config.AllowCutTilesAndBreakables && Main.tileCut[Main.tile[tileX, tileY].type]) + if (TShock.Config.AllowCutTilesAndBreakables && Main.tileCut[tile.type]) { + if (action == EditAction.KillWall) + { + args.Player.SendTileSquare(tileX, tileY, 1); + return true; + } return false; } From 43270a4c1a939583adbf9135ed27fc9fbbafa7a9 Mon Sep 17 00:00:00 2001 From: White Date: Mon, 2 Jan 2017 22:11:36 +1030 Subject: [PATCH 15/17] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1943f4c..dd5ffecdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,17 @@ 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 +* Compatibility with Terraria 1.3.4.4 * API: Version tick 2.0 * API: Added TSPlayer.KillPlayer() (@WhiteXZ) * API: Added TSPlayer.Logout() (@ProfessorXZ) * Fixed connections after max slot is reached (@DeathCradle) * Fixed server crashes caused by client disconnections when attempting to read closed sockets (@Enerdy) +* Added some code to make trapdoors work better (@DogooFalchion) +* AllowCutTilesAndBreakables config option now correctly allows flowers/vines/herbs to be cut in regions without breaking walls (@WhiteXZ) +* REST: `/status` has been re-added. It will now always point to `/v2/server/status` and includes an `upgrade` field describing the newest status route (@WhiteXZ) +* REST: `/v3/players/read` now includes a `muted` field (@WhiteXZ) +* Fixed fishing quests not saving/loading correctly when login before join, UUID login, and SSC were enabled together (@DogooFalchion) ## TShock 4.3.21 * Compatibility with Terraria 1.3.4.3 (@Patrikkk, @Zaicon). From 16df7dc1e8120a544f06e2b63cac28b29d8b7839 Mon Sep 17 00:00:00 2001 From: White Date: Tue, 3 Jan 2017 21:48:20 +1030 Subject: [PATCH 16/17] Submodule update + Changelog update --- CHANGELOG.md | 1 + TerrariaServerAPI | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd5ffecdf..21ee1b408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin ## Upcoming Changes * Compatibility with Terraria 1.3.4.4 * API: Version tick 2.0 +* API: Reduced RAM usage by ~80MB (Large server) (@deathcradle) * API: Added TSPlayer.KillPlayer() (@WhiteXZ) * API: Added TSPlayer.Logout() (@ProfessorXZ) * Fixed connections after max slot is reached (@DeathCradle) diff --git a/TerrariaServerAPI b/TerrariaServerAPI index ecb3b742b..ca93c2d67 160000 --- a/TerrariaServerAPI +++ b/TerrariaServerAPI @@ -1 +1 @@ -Subproject commit ecb3b742b795fb489f9fb6f8ee1c17667f64f85a +Subproject commit ca93c2d6719ee59bb791cff500b1d9d32bb74547 From 06f813c203f9bd2a937d48a663a3dd972601c620 Mon Sep 17 00:00:00 2001 From: White Date: Tue, 3 Jan 2017 21:51:50 +1030 Subject: [PATCH 17/17] Release procedure --- CHANGELOG.md | 2 ++ TShockAPI/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21ee1b408..05cc8a01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 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 + +## TShock 4.3.22 * Compatibility with Terraria 1.3.4.4 * API: Version tick 2.0 * API: Reduced RAM usage by ~80MB (Large server) (@deathcradle) diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index 816fe778b..ad8216817 100644 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -53,5 +53,5 @@ You should have received a copy of the GNU General Public License // Also, be sure to release on github with the exact assembly version tag as below // so that the update manager works correctly (via the Github releases api and mimic) -[assembly: AssemblyVersion("4.3.21")] -[assembly: AssemblyFileVersion("4.3.21")] +[assembly: AssemblyVersion("4.3.22")] +[assembly: AssemblyFileVersion("4.3.22")]