diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 529df43f..0fef3868 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -735,7 +735,7 @@ namespace TShockAPI var group = TShock.Utils.GetGroup(user.Group); - if (TShock.Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { if (group.HasPermission(Permissions.bypassssc)) { @@ -758,7 +758,7 @@ namespace TShockAPI args.Player.IsLoggedIn = true; args.Player.IgnoreActionsForInventory = "none"; - if (!args.Player.IgnoreActionsForClearingTrashCan && TShock.Config.ServerSideCharacter) + if (!args.Player.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter) { args.Player.PlayerData.CopyCharacter(args.Player); TShock.CharacterDB.InsertPlayerData(args.Player); @@ -1347,7 +1347,7 @@ namespace TShockAPI private static void SaveSSC(CommandArgs args) { - if (TShock.Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { args.Player.SendSuccessMessage("SSC has been saved."); foreach (TSPlayer player in TShock.Players) @@ -1362,7 +1362,7 @@ namespace TShockAPI private static void OverrideSSC(CommandArgs args) { - if (!TShock.Config.ServerSideCharacter) + if (!Main.ServerSideCharacter) { args.Player.SendErrorMessage("Server Side Characters is disabled."); return; @@ -1473,7 +1473,7 @@ namespace TShockAPI private static void Off(CommandArgs args) { - if (TShock.Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { foreach (TSPlayer player in TShock.Players) { diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs index fefc4212..9fe81169 100755 --- a/TShockAPI/ConfigFile.cs +++ b/TShockAPI/ConfigFile.cs @@ -201,15 +201,6 @@ namespace TShockAPI [Description("Disables the dungeon guardian from being spawned by player packets, this will instead force a respawn.")] public bool DisableDungeonGuardian; - [Description("Enable server side characters, This stops the client from saving character data! EXPERIMENTAL!!!!!")] - public bool ServerSideCharacter; - - [Description("How often SSC should save, in minutes.")] - public int ServerSideCharacterSave = 5; - - [Description("Time, in milliseconds, to disallow discarding items after logging in when ServerSideInventory is ON.")] - public int LogonDiscardThreshold = 250; - [Description("Disables clown bomb projectiles from spawning.")] public bool DisableClownBombs; diff --git a/TShockAPI/DB/CharacterManager.cs b/TShockAPI/DB/CharacterManager.cs index ba440a8c..db9cff87 100755 --- a/TShockAPI/DB/CharacterManager.cs +++ b/TShockAPI/DB/CharacterManager.cs @@ -18,6 +18,7 @@ along with this program. If not, see . using System; using System.Data; +using System.Text; using MySql.Data.MySqlClient; using Terraria; @@ -102,11 +103,36 @@ namespace TShockAPI.DB public bool SeedInitialData(User user) { - string initialItems = "-15,1,0~-13,1,0~-16,1,45~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0~0,0,0"; + var inventory = new StringBuilder(); + for (int i = 0; i < Terraria.Main.maxInventory; i++) + { + if (i > 0) + { + inventory.Append("~"); + } + if (i < TShock.ServerSideCharacterConfig.StartingInventory.Count) + { + var item = TShock.ServerSideCharacterConfig.StartingInventory[i]; + inventory.Append(item.netID).Append(',').Append(item.stack).Append(',').Append(item.prefix); + } + else + { + inventory.Append("0,0,0"); + } + } + string initialItems = inventory.ToString(); try { - database.Query("INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, spawnX, spawnY, questsCompleted) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8);", user.ID, - 100, 100, 20, 20, initialItems, -1, -1, 0); + database.Query("INSERT INTO tsCharacter (Account, Health, MaxHealth, Mana, MaxMana, Inventory, spawnX, spawnY, questsCompleted) VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8);", + user.ID, + TShock.ServerSideCharacterConfig.StartingHealth, + TShock.ServerSideCharacterConfig.StartingHealth, + TShock.ServerSideCharacterConfig.StartingMana, + TShock.ServerSideCharacterConfig.StartingMana, + initialItems, + -1, + -1, + 0); return true; } catch (Exception ex) diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs index 581fe393..d6205324 100644 --- a/TShockAPI/FileTools.cs +++ b/TShockAPI/FileTools.cs @@ -18,6 +18,7 @@ along with this program. If not, see . using System; using System.IO; +using TShockAPI.ServerSideCharacters; namespace TShockAPI { @@ -55,6 +56,14 @@ namespace TShockAPI get { return Path.Combine(TShock.SavePath, "config.json"); } } + /// + /// Path to the file containing the config. + /// + internal static string ServerSideCharacterConfigPath + { + get { return Path.Combine(TShock.SavePath, "sscconfig.json"); } + } + /// /// Creates an empty file at the given path. /// @@ -98,6 +107,12 @@ namespace TShockAPI } TShock.Config.Write(ConfigPath); + if (File.Exists(ServerSideCharacterConfigPath)) + { + TShock.ServerSideCharacterConfig = ServerSideConfig.Read(ServerSideCharacterConfigPath); + // Add all the missing config properties in the json file + } + TShock.ServerSideCharacterConfig.Write(ServerSideCharacterConfigPath); } /// diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index da0a4479..dc70db27 100755 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1306,7 +1306,7 @@ namespace TShockAPI args.Player.PlayerData.StoreSlot(slot, type, prefix, stack); } else if ( - TShock.Config.ServerSideCharacter && TShock.Config.DisableLoginBeforeJoin && !bypassTrashCanCheck && + Main.ServerSideCharacter && TShock.Config.DisableLoginBeforeJoin && !bypassTrashCanCheck && args.Player.HasSentInventory && !args.Player.Group.HasPermission(Permissions.bypassssc) ) { // The player might have moved an item to their trash can before they performed a single login attempt yet. @@ -1453,7 +1453,7 @@ namespace TShockAPI var group = TShock.Utils.GetGroup(user.Group); - if (TShock.Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { if (group.HasPermission(Permissions.bypassssc)) { @@ -1476,7 +1476,7 @@ namespace TShockAPI args.Player.IsLoggedIn = true; args.Player.IgnoreActionsForInventory = "none"; - if (!args.Player.IgnoreActionsForClearingTrashCan && TShock.Config.ServerSideCharacter) + if (!args.Player.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter) { args.Player.PlayerData.CopyCharacter(args.Player); TShock.CharacterDB.InsertPlayerData(args.Player); @@ -1531,7 +1531,7 @@ namespace TShockAPI var group = TShock.Utils.GetGroup(user.Group); - if (TShock.Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { if (group.HasPermission(Permissions.bypassssc)) { @@ -1554,7 +1554,7 @@ namespace TShockAPI args.Player.IsLoggedIn = true; args.Player.IgnoreActionsForInventory = "none"; - if (!args.Player.IgnoreActionsForClearingTrashCan && TShock.Config.ServerSideCharacter) + if (!args.Player.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter) { args.Player.PlayerData.CopyCharacter(args.Player); TShock.CharacterDB.InsertPlayerData(args.Player); @@ -1965,7 +1965,7 @@ namespace TShockAPI args.Player.SendTileSquare(tileX, tileY, 4); return true; } - if (action == EditAction.PlaceTile && (editData == 29 || editData == 97) && TShock.Config.ServerSideCharacter) + if (action == EditAction.PlaceTile && (editData == 29 || editData == 97) && Main.ServerSideCharacter) { args.Player.SendErrorMessage("You cannot place this tile because server side characters are enabled."); args.Player.SendTileSquare(tileX, tileY, 3); @@ -2625,7 +2625,7 @@ namespace TShockAPI } } - if (args.TPlayer.difficulty == 2 && TShock.Config.ServerSideCharacter && args.Player.IsLoggedIn) + if (args.TPlayer.difficulty == 2 && Main.ServerSideCharacter && args.Player.IsLoggedIn) { User user = TShock.Users.GetUserByName(args.Player.UserAccountName); if (TShock.CharacterDB.RemovePlayer(user.ID)) @@ -2826,7 +2826,7 @@ namespace TShockAPI else args.Player.InitSpawn = true; - if ((TShock.Config.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))) + 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))) { args.Player.sX=args.TPlayer.SpawnX; @@ -2836,7 +2836,7 @@ namespace TShockAPI args.Player.Teleport(args.Player.sX * 16, (args.Player.sY * 16) -48); } - else if ((TShock.Config.ServerSideCharacter) && (args.Player.sX > 0) && (args.Player.sY > 0)) + 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); @@ -3098,7 +3098,7 @@ namespace TShockAPI args.Player.SendData(PacketTypes.ItemDrop, "", id); return true; } - if ((TShock.Config.ServerSideCharacter) && (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond - args.Player.LoginMS < TShock.Config.LogonDiscardThreshold)) + if ((Main.ServerSideCharacter) && (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond - args.Player.LoginMS < TShock.ServerSideCharacterConfig.LogonDiscardThreshold)) { //Player is probably trying to sneak items onto the server in their hands!!! Log.ConsoleInfo(string.Format("Player {0} tried to sneak {1} onto the server!", args.Player.Name, item.name)); diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index e2f85e5b..cfdc99a2 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -260,7 +260,7 @@ namespace TShockAPI rules.Add("PvPMode", TShock.Config.PvPMode); rules.Add("SpawnProtection", TShock.Config.SpawnProtection); rules.Add("SpawnProtectionRadius", TShock.Config.SpawnProtectionRadius); - rules.Add("ServerSideInventory", TShock.Config.ServerSideCharacter); + rules.Add("ServerSideInventory", Main.ServerSideCharacter); ret.Add("rules", rules); } diff --git a/TShockAPI/ServerSideCharacters/ServerSideConfig.cs b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs new file mode 100644 index 00000000..3df944f3 --- /dev/null +++ b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.UI; +using Newtonsoft.Json; + +namespace TShockAPI.ServerSideCharacters +{ + public class ServerSideConfig + { + [Description("Enable server side characters, This stops the client from saving character data! EXPERIMENTAL!!!!!")] + public bool Enabled; + + [Description("How often SSC should save, in minutes.")] + public int ServerSideCharacterSave = 5; + + [Description("Time, in milliseconds, to disallow discarding items after logging in when ServerSideInventory is ON.")] + public int LogonDiscardThreshold = 250; + + [Description("The starting default health for new SSC.")] + public int StartingHealth = 100; + + [Description("The starting default mana for new SSC.")] + public int StartingMana = 20; + + [Description("The starting default inventory for new SSC.")] + public List StartingInventory = new List(); + + public static ServerSideConfig Read(string path) + { + using (var reader = new StreamReader(path)) + { + string txt = reader.ReadToEnd(); + var config = JsonConvert.DeserializeObject(txt); + return config; + } + } + + public void Write(string path) + { + using (var writer = new StreamWriter(path)) + { + writer.Write(JsonConvert.SerializeObject(this, Formatting.Indented)); + } + } + } +} diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 9c957747..5ad87b25 100755 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -379,7 +379,7 @@ namespace TShockAPI /// bool - True/false if it saved successfully public bool SaveServerCharacter() { - if (!TShock.Config.ServerSideCharacter) + if (!Main.ServerSideCharacter) { return false; } @@ -402,7 +402,7 @@ namespace TShockAPI /// bool - True/false if it saved successfully public bool SendServerCharacter() { - if (!TShock.Config.ServerSideCharacter) + if (!Main.ServerSideCharacter) { return false; } @@ -1129,10 +1129,10 @@ namespace TShockAPI public class PlayerData { public NetItem[] inventory = new NetItem[NetItem.maxNetInventory]; - public int health = 100; - public int maxHealth = 100; - public int mana = 20; - public int maxMana = 20; + public int health = TShock.ServerSideCharacterConfig.StartingHealth; + public int maxHealth = TShock.ServerSideCharacterConfig.StartingHealth; + public int mana = TShock.ServerSideCharacterConfig.StartingMana; + public int maxMana = TShock.ServerSideCharacterConfig.StartingMana; public bool exists; public int spawnX= -1; public int spawnY= -1; @@ -1166,7 +1166,12 @@ namespace TShockAPI this.inventory[2].stack = 1; if (player.TPlayer.inventory[2] != null && player.TPlayer.inventory[2].netID == -16) this.inventory[2].prefix = player.TPlayer.inventory[2].prefix; - + + for (int i = 0; i < TShock.ServerSideCharacterConfig.StartingInventory.Count; i++) + { + var item = TShock.ServerSideCharacterConfig.StartingInventory[i]; + StoreSlot(i, item.netID, item.prefix, item.stack); + } } public void StoreSlot(int slot, int netID, int prefix, int stack) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 48e72605..93e4547a 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -38,6 +38,7 @@ using TShockAPI.DB; using TShockAPI.Net; using System.Threading; using System.Threading.Tasks; +using TShockAPI.ServerSideCharacters; namespace TShockAPI { @@ -66,6 +67,7 @@ namespace TShockAPI public static RememberedPosManager RememberedPos; public static CharacterManager CharacterDB; public static ConfigFile Config { get; set; } + public static ServerSideConfig ServerSideCharacterConfig; public static IDbConnection DB; public static bool OverridePort; public static PacketBufferer PacketBuffer; @@ -112,6 +114,10 @@ namespace TShockAPI : base(game) { Config = new ConfigFile(); + ServerSideCharacterConfig = new ServerSideConfig(); + ServerSideCharacterConfig.StartingInventory.Add(new NetItem { netID = -15, prefix = 0, stack = 1 }); + ServerSideCharacterConfig.StartingInventory.Add(new NetItem { netID = -13, prefix = 0, stack = 1 }); + ServerSideCharacterConfig.StartingInventory.Add(new NetItem { netID = -16, prefix = 0, stack = 1 }); Order = 0; } @@ -132,7 +138,7 @@ namespace TShockAPI ConfigFile.ConfigRead += OnConfigRead; FileTools.SetupConfig(); - Main.ServerSideCharacter = Config.ServerSideCharacter; + Main.ServerSideCharacter = ServerSideCharacterConfig.Enabled; DateTime now = DateTime.Now; string logFilename; @@ -658,7 +664,7 @@ namespace TShockAPI LastCheck = DateTime.UtcNow; } - if (TShock.Config.ServerSideCharacter && (DateTime.UtcNow - LastSave).TotalMinutes >= Config.ServerSideCharacterSave) + if (Main.ServerSideCharacter && (DateTime.UtcNow - LastSave).TotalMinutes >= ServerSideCharacterConfig.ServerSideCharacterSave) { foreach (TSPlayer player in Players) { @@ -725,13 +731,13 @@ namespace TShockAPI if (player.RecentFuse >0) player.RecentFuse--; - if ((TShock.Config.ServerSideCharacter) && (player.TPlayer.SpawnX > 0) &&(player.sX != player.TPlayer.SpawnX)) + if ((Main.ServerSideCharacter) && (player.TPlayer.SpawnX > 0) &&(player.sX != player.TPlayer.SpawnX)) { player.sX=player.TPlayer.SpawnX; player.sY=player.TPlayer.SpawnY; } - if ((TShock.Config.ServerSideCharacter) && (player.sX > 0) && (player.sY > 0) && (player.TPlayer.SpawnX < 0)) + if ((Main.ServerSideCharacter) && (player.sX > 0) && (player.sY > 0) && (player.TPlayer.SpawnX < 0)) { player.TPlayer.SpawnX = player.sX; player.TPlayer.SpawnY = player.sY; @@ -991,7 +997,7 @@ namespace TShockAPI Utils.Broadcast(tsplr.Name + " has left.", Color.Yellow); Log.Info(string.Format("{0} disconnected.", tsplr.Name)); - if (tsplr.IsLoggedIn && !tsplr.IgnoreActionsForClearingTrashCan && TShock.Config.ServerSideCharacter && (!tsplr.Dead || tsplr.TPlayer.difficulty != 2)) + if (tsplr.IsLoggedIn && !tsplr.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter && (!tsplr.Dead || tsplr.TPlayer.difficulty != 2)) { tsplr.PlayerData.CopyCharacter(tsplr); CharacterDB.InsertPlayerData(tsplr); @@ -1213,7 +1219,7 @@ namespace TShockAPI if (!player.IsLoggedIn) { - if (Config.ServerSideCharacter) + if (Main.ServerSideCharacter) { player.SendMessage( player.IgnoreActionsForInventory = "Server side characters is enabled! Please /register or /login to play!", diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index c1458488..6d8b0d64 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -122,6 +122,7 @@ + @@ -179,7 +180,7 @@ - +