diff --git a/.travis.yml b/.travis.yml index 22e6ce9b..622133dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ -language: c -install: -- sudo apt-get install mono-devel mono-gmcs nunit-console -script: -- xbuild ./TShockAPI/TShockAPI.csproj +language: csharp +solution: ./TShockAPI/TShockAPI.csproj notifications: - irc: irc.rizon.net#tshock hipchat: - secure: hpRLWiHF2j6O2qJOVs++aqAmryN6G5kY0SF26/rKCpQ7klhMlDZIgI1V1dbkKqlculFtW1neS0EBJyV9lmcV5b26H+KhlZYGN0j7q1VcOTM3rvtU6wW0Ap22uRLl2RrnA4kEsgDAsNouPOkyLZ19hlHAISlsId6G4+Rfqg6k+zQ= \ No newline at end of file + secure: hpRLWiHF2j6O2qJOVs++aqAmryN6G5kY0SF26/rKCpQ7klhMlDZIgI1V1dbkKqlculFtW1neS0EBJyV9lmcV5b26H+KhlZYGN0j7q1VcOTM3rvtU6wW0Ap22uRLl2RrnA4kEsgDAsNouPOkyLZ19hlHAISlsId6G4+Rfqg6k+zQ= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 095ad8ea..f7337cb9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,36 +1,40 @@ ### Issue Guidelines Please follow these simple requirements before posting an issue: -1. TShock version number -2. Any stack traces that may have happened when the issue occurred -3. How to reproduce the issue +- TShock version number +- Any stack traces that may have happened when the issue occurred +- How to reproduce the issue +- Screenshots of the issue (if applicable) + +### TShock Additions + +If something is better suited to be a plugin for TShock, rather than a TShock core feature, it should not be added! ### Pull Request Dev Guidelines -These guidelines are for contributors. If you do not follow these guidelines your commits will be reverted. +These guidelines are for all contributors. Required: -- Follow the code style. We generally use microsofts except for m_ infront of private variables. -- Do not push unfinished features to the master branch, instead create a remote branch and push to that. -- Do not push untested code to the master branch, instead push to the test branch. -- Document all compatibility issues in the COMPATIBILITY file. (IE file formats changing) -- DO NOT MASS COMMIT. Commit changes as you go (without pushing). That way when you push we don't get a thousand changes with a 1-3 line commit message. - -Optional: -- Build Version Increment (http://autobuildversion.codeplex.com/). - ----- +- Push code to the general-devel branch. Do not push it anywhere else. +- Use tabs, not spaces. +- Use UpperCamelCase for public function names. +- Prior to developing, make sure your clone is up to date with general-devel. This means that we don't get merge commits in your pull request. ### Dev Team Guidelines These guidelines are to be followed by all developers with commit level access to this repository: -- Do not, for any reason, submit code to the master branch before it hits the development branch first. If the development branch is far ahead, and a new bug fix is going out, branch master, then merge with master and remove your branch. - - If you are found to do this, you will be the person merging and rebasing your code to fit general-devel. - Prior to posting any version on the website, you must tick the version in AssemblyInfo.cs. This is the versioning formula: - - Major.Minor.Revision.BuildDate (tick Revision if you're fixing prior to an actual planned release) + - Major.Minor.Revision - Do not release any development builds on the forums without consulting another developer first. -- __Document code prior to marking it done in JIRA__ -- Move any un-tested code to the "Needs Validation" section on JIRA prior to marking it as done. -- Do not push changes to any branch without a proper issue being assigned in JIRA. If a feature isn't planned for this release, __it shouldn't be in the repo about to be released__. -- Submit all pull requests to the general-devel branch prior to the master branch, or you will be ignored. \ No newline at end of file +- This is not a professional software product. Your results may vary with code quality, buginess, etc. Do not complain about something -- just fix it and move on. +- __Do not force push the repo__, or you will be removed. +- __Do not revert commits__, unless you have sign-off from one other developer (the two-man rule), or you will be removed. +- __This is not a meritocracy.__ + +#### Pull Request Acceptance Guidelines + +- Don't ruin someone's first time sending a pull request. They feel demotivated, and then they won't want to push any more code for us. +- Don't accept untested pull requests from the outside world. Bamboo and Travis will at least make sure that something compiles, but actual code and execution tests are required. +- Pull request acceptance from internal contributors (anyone with write access) requires only one other approval to merge. +- Pull request acceptance from external contributors (anyone without write access) requires the [two-man rule](https://en.wikipedia.org/wiki/Two-man_rule) to be followed. If another man/woman/child in the two-man rule cannot be found within seven days, then this requirement is exempted. diff --git a/README.md b/README.md index 13d50d62..72479628 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,3 @@ -# Current Status -This project is in maintenance mode. This means that the core team of developers' time is very limited, and only extremely game breaking bugs will be fixed. Improvements, new features, and minor issues will not be resolved by direct development until this time restriction has passed. Issues created reflecting these requests will not be worked on until this notice is removed. - -Thanks for your continued support of TShock for Terraria. - # TShock [![Build Status](https://travis-ci.org/NyxStudios/TShock.png?branch=general-devel)](https://travis-ci.org/NyxStudios/TShock) TShock is a server modification for Terraria, written in C#, and based upon the [Terraria Server API](https://github.com/Deathmax/TerrariaAPI-Server). It uses JSON for configuration management, and offers several features not present in the Terraria Server normally. @@ -21,11 +16,11 @@ TShock is a server modification for Terraria, written in C#, and based upon the Feeling like helping out? Want to find an awesome server? Some awesome plugins? -* [Website & Forums](http://tshock.co/xf/) +* [Website & Forums](https://tshock.co/xf/) * [Wiki](https://tshock.atlassian.net/wiki/display/TSHOCKPLUGINS/Home) -* [IRC: #tshock @ irc.rizon.net](http://tshock.co/xf/index.php?ezirc/) ## Download * [Github Releases](https://github.com/TShock/TShock/releases) -* [Download Archive](https://github.com/TShock/TShock/downloads) +* [Plugins](https://tshock.co/xf/index.php?resources/) +* [Very, very old versions of TShock](https://github.com/TShock/TShock/downloads) diff --git a/TShockAPI/BackupManager.cs b/TShockAPI/BackupManager.cs index 1882d0bb..deb22658 100644 --- a/TShockAPI/BackupManager.cs +++ b/TShockAPI/BackupManager.cs @@ -61,13 +61,13 @@ namespace TShockAPI if (worldpath != null && !Directory.Exists(worldpath)) Directory.CreateDirectory(worldpath); - TShock.Utils.Broadcast("Server map saving, potential lag spike."); + TSPlayer.All.SendInfoMessage("Server map saving, potential lag spike."); Console.WriteLine("Backing up world..."); SaveManager.Instance.SaveWorld(); Console.WriteLine("World backed up."); Console.ForegroundColor = ConsoleColor.Gray; - Log.Info(string.Format("World backed up ({0}).", Main.worldPathName)); + TShock.Log.Info(string.Format("World backed up ({0}).", Main.worldPathName)); Main.worldPathName = worldname; } @@ -76,8 +76,8 @@ namespace TShockAPI Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Backup failed!"); Console.ForegroundColor = ConsoleColor.Gray; - Log.Error("Backup failed!"); - Log.Error(ex.ToString()); + TShock.Log.Error("Backup failed!"); + TShock.Log.Error(ex.ToString()); } } diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index ec378ae0..f186e688 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -37,6 +37,7 @@ namespace TShockAPI { public string Message { get; private set; } public TSPlayer Player { get; private set; } + public bool Silent { get; private set; } /// /// Parameters passed to the arguement. Does not include the command name. @@ -54,6 +55,15 @@ namespace TShockAPI Message = message; Player = ply; Parameters = args; + Silent = false; + } + + public CommandArgs(string message, bool silent, TSPlayer ply, List args) + { + Message = message; + Player = ply; + Parameters = args; + Silent = silent; } } @@ -124,29 +134,34 @@ namespace TShockAPI CommandDelegate = cmd; DoLog = true; HelpText = "No help available."; - HelpDesc = null; + HelpDesc = null; Names = new List(names); Permissions = new List(); } - public bool Run(string msg, TSPlayer ply, List parms) + public bool Run(string msg, bool silent, TSPlayer ply, List parms) { if (!CanRun(ply)) return false; try { - CommandDelegate(new CommandArgs(msg, ply, parms)); + CommandDelegate(new CommandArgs(msg, silent, ply, parms)); } catch (Exception e) { ply.SendErrorMessage("Command failed, check logs for more details."); - Log.Error(e.ToString()); + TShock.Log.Error(e.ToString()); } return true; } + public bool Run(string msg, TSPlayer ply, List parms) + { + return Run(msg, false, ply, parms); + } + public bool HasAlias(string name) { return Names.Contains(name); @@ -170,6 +185,16 @@ namespace TShockAPI public static List ChatCommands = new List(); public static ReadOnlyCollection TShockCommands = new ReadOnlyCollection(new List()); + public static string Specifier + { + get { return string.IsNullOrWhiteSpace(TShock.Config.CommandSpecifier) ? "/" : TShock.Config.CommandSpecifier; } + } + + public static string SilentSpecifier + { + get { return string.IsNullOrWhiteSpace(TShock.Config.CommandSilentSpecifier) ? "." : TShock.Config.CommandSilentSpecifier; } + } + private delegate void AddChatCommand(string permission, CommandDelegate command, params string[] names); public static void InitCommands() @@ -542,7 +567,7 @@ namespace TShockAPI { HelpText = "Slaps a player, dealing damage." }); - add(new Command(Permissions.serverinfo, ServerInfo, "stats") + add(new Command(Permissions.serverinfo, ServerInfo, "serverinfo") { HelpText = "Shows the server information." }); @@ -583,6 +608,11 @@ namespace TShockAPI public static bool HandleCommand(TSPlayer player, string text) { string cmdText = text.Remove(0, 1); + string cmdPrefix = text[0].ToString(); + bool silent = false; + + if (cmdPrefix == SilentSpecifier) + silent = true; var args = ParseParameters(cmdText); if (args.Count < 1) @@ -591,7 +621,7 @@ namespace TShockAPI string cmdName = args[0].ToLower(); args.RemoveAt(0); - IEnumerable cmds = ChatCommands.Where(c => c.HasAlias(cmdName)).ToList(); + IEnumerable cmds = ChatCommands.FindAll(c => c.HasAlias(cmdName)); if (Hooks.PlayerHooks.OnPlayerCommand(player, cmdName, cmdText, args, ref cmds)) return true; @@ -605,28 +635,28 @@ namespace TShockAPI call(new CommandArgs(cmdText, player, args)); return true; } - player.SendErrorMessage("Invalid command entered. Type {0}help for a list of valid commands.", TShock.Config.CommandSpecifier); + player.SendErrorMessage("Invalid command entered. Type {0}help for a list of valid commands.", Specifier); return true; } - foreach (Command cmd in cmds) - { - if (!cmd.CanRun(player)) - { - TShock.Utils.SendLogs(string.Format("{0} tried to execute {1}{2}.", player.Name, TShock.Config.CommandSpecifier, cmdText), Color.PaleVioletRed, player); - player.SendErrorMessage("You do not have access to this command."); - } - else if (!cmd.AllowServer && !player.RealPlayer) - { - player.SendErrorMessage("You must use this command in-game."); - } - else - { - if (cmd.DoLog) - TShock.Utils.SendLogs(string.Format("{0} executed: {1}{2}.", player.Name, TShock.Config.CommandSpecifier, cmdText), Color.PaleVioletRed, player); - cmd.Run(cmdText, player, args); - } - } - return true; + foreach (Command cmd in cmds) + { + if (!cmd.CanRun(player)) + { + TShock.Utils.SendLogs(string.Format("{0} tried to execute {1}{2}.", player.Name, Specifier, cmdText), Color.PaleVioletRed, player); + player.SendErrorMessage("You do not have access to this command."); + } + else if (!cmd.AllowServer && !player.RealPlayer) + { + player.SendErrorMessage("You must use this command in-game."); + } + else + { + if (cmd.DoLog) + TShock.Utils.SendLogs(string.Format("{0} executed: {1}{2}.", player.Name, silent ? SilentSpecifier : Specifier, cmdText), Color.PaleVioletRed, player); + cmd.Run(cmdText, silent, player, args); + } + } + return true; } /// @@ -691,7 +721,7 @@ namespace TShockAPI { if (args.Player.LoginAttempts > TShock.Config.MaximumLoginAttempts && (TShock.Config.MaximumLoginAttempts != -1)) { - Log.Warn(String.Format("{0} ({1}) had {2} or more invalid login attempts and was kicked automatically.", + TShock.Log.Warn(String.Format("{0} ({1}) had {2} or more invalid login attempts and was kicked automatically.", args.Player.IP, args.Player.Name, TShock.Config.MaximumLoginAttempts)); TShock.Utils.Kick(args.Player, "Too many invalid login attempts."); return; @@ -729,9 +759,9 @@ namespace TShockAPI } else { - args.Player.SendErrorMessage("Syntax: /login - Logs in using your UUID and character name"); - args.Player.SendErrorMessage(" /login - Logs in using your password and character name"); - args.Player.SendErrorMessage(" /login - Logs in using your username and password"); + args.Player.SendErrorMessage("Syntax: {0}login - Logs in using your UUID and character name", Specifier); + args.Player.SendErrorMessage(" {0}login - Logs in using your password and character name", Specifier); + args.Player.SendErrorMessage(" {0}login - Logs in using your username and password", Specifier); args.Player.SendErrorMessage("If you forgot your password, there is no way to recover it."); return; } @@ -779,7 +809,7 @@ namespace TShockAPI } args.Player.SendSuccessMessage("Authenticated as " + user.Name + " successfully."); - Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user: " + user.Name + "."); + TShock.Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user: " + user.Name + "."); if ((args.Player.LoginHarassed) && (TShock.Config.RememberLeavePos)) { if (TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP) != Vector2.Zero) @@ -804,14 +834,14 @@ namespace TShockAPI { args.Player.SendErrorMessage("Invalid password!"); } - Log.Warn(args.Player.IP + " failed to authenticate as user: " + user.Name + "."); + TShock.Log.Warn(args.Player.IP + " failed to authenticate as user: " + user.Name + "."); args.Player.LoginAttempts++; } } catch (Exception ex) { args.Player.SendErrorMessage("There was an error processing your request."); - Log.Error(ex.ToString()); + TShock.Log.Error(ex.ToString()); } } @@ -827,24 +857,24 @@ namespace TShockAPI { args.Player.SendSuccessMessage("You changed your password!"); TShock.Users.SetUserPassword(user, args.Parameters[1]); // SetUserPassword will hash it for you. - Log.ConsoleInfo(args.Player.IP + " named " + args.Player.Name + " changed the password of account " + user.Name + "."); + TShock.Log.ConsoleInfo(args.Player.IP + " named " + args.Player.Name + " changed the password of account " + user.Name + "."); } else { args.Player.SendErrorMessage("You failed to change your password!"); - Log.ConsoleError(args.Player.IP + " named " + args.Player.Name + " failed to change password for account: " + + TShock.Log.ConsoleError(args.Player.IP + " named " + args.Player.Name + " failed to change password for account: " + user.Name + "."); } } else { - args.Player.SendErrorMessage("Not logged in or invalid syntax! Proper syntax: /password "); + args.Player.SendErrorMessage("Not logged in or invalid syntax! Proper syntax: {0}password ", Specifier); } } catch (UserManagerException ex) { args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + "."); - Log.ConsoleError("PasswordUser returned an error: " + ex); + TShock.Log.ConsoleError("PasswordUser returned an error: " + ex); } } @@ -866,7 +896,7 @@ namespace TShockAPI } else { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /register "); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}register ", Specifier); return; } @@ -878,19 +908,18 @@ namespace TShockAPI args.Player.SendSuccessMessage("Account \"{0}\" has been registered.", user.Name); args.Player.SendSuccessMessage("Your password is {0}.", user.Password); TShock.Users.AddUser(user); - TShock.CharacterDB.SeedInitialData(TShock.Users.GetUser(user)); - Log.ConsoleInfo("{0} registered an account: \"{1}\".", args.Player.Name, user.Name); + TShock.Log.ConsoleInfo("{0} registered an account: \"{1}\".", args.Player.Name, user.Name); } else { args.Player.SendErrorMessage("Account " + user.Name + " has already been registered."); - Log.ConsoleInfo(args.Player.Name + " failed to register an existing account: " + user.Name); + TShock.Log.ConsoleInfo(args.Player.Name + " failed to register an existing account: " + user.Name); } } catch (UserManagerException ex) { args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + "."); - Log.ConsoleError("RegisterUser returned an error: " + ex); + TShock.Log.ConsoleError("RegisterUser returned an error: " + ex); } } @@ -899,7 +928,7 @@ namespace TShockAPI // This guy needs to be here so that people don't get exceptions when they type /user if (args.Parameters.Count < 1) { - args.Player.SendErrorMessage("Invalid user syntax. Try /user help."); + args.Player.SendErrorMessage("Invalid user syntax. Try {0}user help.", Specifier); return; } @@ -919,27 +948,26 @@ namespace TShockAPI try { TShock.Users.AddUser(user); - TShock.CharacterDB.SeedInitialData(TShock.Users.GetUser(user)); args.Player.SendSuccessMessage("Account " + user.Name + " has been added to group " + user.Group + "!"); - Log.ConsoleInfo(args.Player.Name + " added Account " + user.Name + " to group " + user.Group); + TShock.Log.ConsoleInfo(args.Player.Name + " added Account " + user.Name + " to group " + user.Group); } - catch (GroupNotExistsException e) + catch (GroupNotExistsException) { args.Player.SendErrorMessage("Group " + user.Group + " does not exist!"); } - catch (UserExistsException e) + catch (UserExistsException) { args.Player.SendErrorMessage("User " + user.Name + " already exists!"); } catch (UserManagerException e) { args.Player.SendErrorMessage("User " + user.Name + " could not be added, check console for details."); - Log.ConsoleError(e.ToString()); + TShock.Log.ConsoleError(e.ToString()); } } else { - args.Player.SendErrorMessage("Invalid syntax. Try /user help."); + args.Player.SendErrorMessage("Invalid syntax. Try {0}user help.", Specifier); } } // User deletion requires a username @@ -952,16 +980,16 @@ namespace TShockAPI { TShock.Users.RemoveUser(user); args.Player.SendSuccessMessage("Account removed successfully."); - Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1] + "."); + TShock.Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1] + "."); } - catch (UserNotExistException e) + catch (UserNotExistException) { args.Player.SendErrorMessage("The user " + user.Name + " does not exist! Deleted nobody!"); } catch (UserManagerException ex) { - args.Player.SendMessage(ex.Message, Color.Red); - Log.ConsoleError(ex.ToString()); + args.Player.SendErrorMessage(ex.Message); + TShock.Log.ConsoleError(ex.ToString()); } } @@ -976,22 +1004,22 @@ namespace TShockAPI try { TShock.Users.SetUserPassword(user, args.Parameters[2]); - Log.ConsoleInfo(args.Player.Name + " changed the password of account " + user.Name); + TShock.Log.ConsoleInfo(args.Player.Name + " changed the password of account " + user.Name); args.Player.SendSuccessMessage("Password change succeeded for " + user.Name + "."); } - catch (UserNotExistException e) + catch (UserNotExistException) { args.Player.SendErrorMessage("User " + user.Name + " does not exist!"); } catch (UserManagerException e) { args.Player.SendErrorMessage("Password change for " + user.Name + " failed! Check console!"); - Log.ConsoleError(e.ToString()); + TShock.Log.ConsoleError(e.ToString()); } } else { - args.Player.SendErrorMessage("Invalid user password syntax. Try /user help."); + args.Player.SendErrorMessage("Invalid user password syntax. Try {0}user help.", Specifier); } } // Group changing requires a username or IP address, and a new group to set @@ -1005,18 +1033,18 @@ namespace TShockAPI try { TShock.Users.SetUserGroup(user, args.Parameters[2]); - Log.ConsoleInfo(args.Player.Name + " changed account " + user.Name + " to group " + args.Parameters[2] + "."); + TShock.Log.ConsoleInfo(args.Player.Name + " changed account " + user.Name + " to group " + args.Parameters[2] + "."); args.Player.SendSuccessMessage("Account " + user.Name + " has been changed to group " + args.Parameters[2] + "!"); } - catch (GroupNotExistsException e) + catch (GroupNotExistsException) { args.Player.SendErrorMessage("That group does not exist!"); } - catch (UserNotExistException e) + catch (UserNotExistException) { args.Player.SendErrorMessage("User " + user.Name + " does not exist!"); } - catch (UserManagerException e) + catch (UserManagerException) { args.Player.SendErrorMessage("User " + user.Name + " could not be added. Check console for details."); } @@ -1024,20 +1052,20 @@ namespace TShockAPI } else { - args.Player.SendErrorMessage("Invalid user group syntax. Try /user help."); + args.Player.SendErrorMessage("Invalid user group syntax. Try {0}user help.", Specifier); } } else if (subcmd == "help") { args.Player.SendInfoMessage("Use command help:"); - args.Player.SendInfoMessage("/user add username password group -- Adds a specified user"); - args.Player.SendInfoMessage("/user del username -- Removes a specified user"); - args.Player.SendInfoMessage("/user password username newpassword -- Changes a user's password"); - args.Player.SendInfoMessage("/user group username newgroup -- Changes a user's group"); + args.Player.SendInfoMessage("{0}user add username password group -- Adds a specified user", Specifier); + args.Player.SendInfoMessage("{0}user del username -- Removes a specified user", Specifier); + args.Player.SendInfoMessage("{0}user password username newpassword -- Changes a user's password", Specifier); + args.Player.SendInfoMessage("{0}user group username newgroup -- Changes a user's group", Specifier); } else { - args.Player.SendErrorMessage("Invalid user syntax. Try /user help."); + args.Player.SendErrorMessage("Invalid user syntax. Try {0}user help.", Specifier); } } @@ -1070,7 +1098,7 @@ namespace TShockAPI { if (args.Parameters.Count < 1) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /userinfo "); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}userinfo ", Specifier); return; } @@ -1094,7 +1122,7 @@ namespace TShockAPI { if (args.Parameters.Count < 1) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /kick [reason]"); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}kick [reason]", Specifier); return; } if (args.Parameters[0].Length == 0) @@ -1135,7 +1163,7 @@ namespace TShockAPI { if (args.Parameters.Count < 2) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /ban add [reason]"); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}ban add [reason]", Specifier); return; } @@ -1154,9 +1182,27 @@ namespace TShockAPI var knownIps = JsonConvert.DeserializeObject>(user.KnownIps); TShock.Bans.AddBan(knownIps.Last(), user.Name, user.UUID, reason, false, args.Player.UserAccountName); if (String.IsNullOrWhiteSpace(args.Player.UserAccountName)) - TSPlayer.All.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "force " : "", reason); + { + if (args.Silent) + { + args.Player.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "Force " : "", reason); + } + else + { + TSPlayer.All.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "Force " : "", reason); + } + } else - TSPlayer.All.SendInfoMessage("{0} {1}banned {2} for '{3}'.", args.Player.Name, force ? "force " : "", user.Name, reason); + { + if (args.Silent) + { + args.Player.SendInfoMessage("{0}banned {1} for '{2}'.", force ? "Force " : "", user.Name, reason); + } + else + { + TSPlayer.All.SendInfoMessage("{0} {1}banned {2} for '{3}'.", args.Player.Name, force ? "Force " : "", user.Name, reason); + } + } } } else @@ -1177,7 +1223,7 @@ namespace TShockAPI { if (args.Parameters.Count < 2) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /ban addip [reason]"); + args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}ban addip [reason]", Specifier); return; } @@ -1195,7 +1241,7 @@ namespace TShockAPI { if (args.Parameters.Count < 3) { - args.Player.SendErrorMessage("Invalid syntax! Proper syntax: /ban addtemp public class TileEditEventArgs : HandledEventArgs { - /// - /// The TSPlayer who made the tile edit - /// - public TSPlayer Player { get; set; } + /// + /// The TSPlayer who made the tile edit + /// + public TSPlayer Player { get; set; } /// /// The tile coordinate on the X plane @@ -87,10 +87,10 @@ namespace TShockAPI /// public EditAction Action { get; set; } - /// - /// Did the tile get destroyed successfully. - /// - public EditType editDetail { get; set; } + /// + /// Did the tile get destroyed successfully. + /// + public EditType editDetail { get; set; } /// /// Used when a tile is placed to denote a subtype of tile. (e.g. for tile id 21: Chest = 0, Gold Chest = 1) @@ -109,12 +109,12 @@ namespace TShockAPI var args = new TileEditEventArgs { - Player = ply, + Player = ply, X = x, Y = y, Action = action, EditData = editData, - editDetail = editDetail, + editDetail = editDetail, Style = style }; TileEdit.Invoke(null, args); @@ -152,37 +152,37 @@ namespace TShockAPI return args.Handled; } - /// - /// For use in a PlayerTeam event - /// - public class PlayerTeamEventArgs : HandledEventArgs - { - /// - /// The Terraria player ID of the player - /// - public byte PlayerId { get; set; } - /// - /// Enable/disable pvp? - /// - public byte Team { get; set; } - } - /// - /// TogglePvp - called when a player toggles pvp - /// - public static HandlerList PlayerTeam; - private static bool OnPlayerTeam(byte _id, byte _team) - { - if (PlayerTeam == null) - return false; + /// + /// For use in a PlayerTeam event + /// + public class PlayerTeamEventArgs : HandledEventArgs + { + /// + /// The Terraria player ID of the player + /// + public byte PlayerId { get; set; } + /// + /// Enable/disable pvp? + /// + public byte Team { get; set; } + } + /// + /// TogglePvp - called when a player toggles pvp + /// + public static HandlerList PlayerTeam; + private static bool OnPlayerTeam(byte _id, byte _team) + { + if (PlayerTeam == null) + return false; - var args = new PlayerTeamEventArgs - { - PlayerId = _id, - Team = _team, - }; - PlayerTeam.Invoke(null, args); - return args.Handled; - } + var args = new PlayerTeamEventArgs + { + PlayerId = _id, + Team = _team, + }; + PlayerTeam.Invoke(null, args); + return args.Handled; + } /// /// For use in a PlayerSlot event @@ -1261,7 +1261,7 @@ namespace TShockAPI } catch (Exception ex) { - Log.Error(ex.ToString()); + TShock.Log.Error(ex.ToString()); return true; } } @@ -1469,7 +1469,7 @@ namespace TShockAPI TShock.CharacterDB.InsertPlayerData(args.Player); } args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen); - Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + "."); + TShock.Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + "."); Hooks.PlayerHooks.OnPlayerPostLogin(args.Player); return true; } @@ -1500,56 +1500,56 @@ namespace TShockAPI string password = args.Data.ReadString(); - if (Hooks.PlayerHooks.OnPlayerPreLogin(args.Player, args.Player.Name, password)) - return true; + if (Hooks.PlayerHooks.OnPlayerPreLogin(args.Player, args.Player.Name, password)) + return true; var user = TShock.Users.GetUserByName(args.Player.Name); - if (user != null && !TShock.Config.DisableLoginBeforeJoin) + if (user != null && !TShock.Config.DisableLoginBeforeJoin) { string encrPass = TShock.Utils.HashPassword(password); if (user.Password.ToUpper() == encrPass.ToUpper()) { - args.Player.RequiresPassword = false; - args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, TShock.Users.GetUserID(args.Player.Name)); + args.Player.RequiresPassword = false; + args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, TShock.Users.GetUserID(args.Player.Name)); - if (args.Player.State == 1) - args.Player.State = 2; - NetMessage.SendData((int) PacketTypes.WorldInfo, args.Player.Index); + if (args.Player.State == 1) + args.Player.State = 2; + NetMessage.SendData((int) PacketTypes.WorldInfo, args.Player.Index); - var group = TShock.Utils.GetGroup(user.Group); + var group = TShock.Utils.GetGroup(user.Group); - if (Main.ServerSideCharacter) - { - if (group.HasPermission(Permissions.bypassssc)) - { - args.Player.IgnoreActionsForClearingTrashCan = false; - } + if (Main.ServerSideCharacter) + { + if (group.HasPermission(Permissions.bypassssc)) + { + args.Player.IgnoreActionsForClearingTrashCan = false; + } args.Player.PlayerData.RestoreCharacter(args.Player); - } + } args.Player.LoginFailsBySsi = false; - if (group.HasPermission(Permissions.ignorestackhackdetection)) - args.Player.IgnoreActionsForCheating = "none"; + if (group.HasPermission(Permissions.ignorestackhackdetection)) + args.Player.IgnoreActionsForCheating = "none"; - if (group.HasPermission(Permissions.usebanneditem)) - args.Player.IgnoreActionsForDisabledArmor = "none"; + if (group.HasPermission(Permissions.usebanneditem)) + args.Player.IgnoreActionsForDisabledArmor = "none"; - args.Player.Group = group; - args.Player.tempGroup = null; - args.Player.UserAccountName = args.Player.Name; - args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName); - args.Player.IsLoggedIn = true; - args.Player.IgnoreActionsForInventory = "none"; + args.Player.Group = group; + args.Player.tempGroup = null; + args.Player.UserAccountName = args.Player.Name; + args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName); + args.Player.IsLoggedIn = true; + args.Player.IgnoreActionsForInventory = "none"; - if (!args.Player.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter) - { - args.Player.PlayerData.CopyCharacter(args.Player); - TShock.CharacterDB.InsertPlayerData(args.Player); - } - args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen); - Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + "."); + if (!args.Player.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter) + { + args.Player.PlayerData.CopyCharacter(args.Player); + TShock.CharacterDB.InsertPlayerData(args.Player); + } + args.Player.SendMessage("Authenticated as " + args.Player.Name + " successfully.", Color.LimeGreen); + TShock.Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user " + args.Player.Name + "."); TShock.Users.SetUserUUID(user, args.Player.UUID); - Hooks.PlayerHooks.OnPlayerPostLogin(args.Player); + Hooks.PlayerHooks.OnPlayerPostLogin(args.Player); return true; } TShock.Utils.ForceKick(args.Player, "Invalid user account password.", true); @@ -1577,7 +1577,7 @@ namespace TShockAPI { if (args.Player.RequestedSection) return true; - args.Player.RequestedSection = true; + args.Player.RequestedSection = true; if (String.IsNullOrEmpty(args.Player.Name)) { TShock.Utils.ForceKick(args.Player, "Blank name.", true); @@ -2180,15 +2180,15 @@ namespace TShockAPI return false; } - private static bool HandlePlayerTeam(GetDataHandlerArgs args) - { - byte id = args.Data.ReadInt8(); - byte team = args.Data.ReadInt8(); - if (OnPlayerTeam(id, team)) - return true; + private static bool HandlePlayerTeam(GetDataHandlerArgs args) + { + byte id = args.Data.ReadInt8(); + byte team = args.Data.ReadInt8(); + if (OnPlayerTeam(id, team)) + return true; - if (id != args.Player.Index) - return true; + if (id != args.Player.Index) + return true; if ((DateTime.UtcNow - args.Player.LastPvPTeamChange).TotalSeconds < 5) { @@ -2197,8 +2197,8 @@ namespace TShockAPI } args.Player.LastPvPTeamChange = DateTime.UtcNow; - return false; - } + return false; + } private static bool HandlePlayerUpdate(GetDataHandlerArgs args) { @@ -2232,34 +2232,30 @@ namespace TShockAPI if (!pos.Equals(args.Player.LastNetPosition)) { float distance = Vector2.Distance(new Vector2(pos.X/16f, pos.Y/16f), - new Vector2(args.Player.LastNetPosition.X/16f, args.Player.LastNetPosition.Y/16f)); + new Vector2(args.Player.LastNetPosition.X/16f, args.Player.LastNetPosition.Y/16f)); if (TShock.CheckIgnores(args.Player)) { if (distance > TShock.Config.MaxRangeForDisabled) { if (args.Player.IgnoreActionsForCheating != "none") { - args.Player.SendMessage("Disabled for cheating: " + args.Player.IgnoreActionsForCheating, - Color.Red); + args.Player.SendErrorMessage("Disabled for cheating: " + args.Player.IgnoreActionsForCheating); } else if (args.Player.IgnoreActionsForDisabledArmor != "none") { - args.Player.SendMessage( - "Disabled for banned armor: " + args.Player.IgnoreActionsForDisabledArmor, Color.Red); + args.Player.SendErrorMessage("Disabled for banned armor: " + args.Player.IgnoreActionsForDisabledArmor); } else if (args.Player.IgnoreActionsForInventory != "none") { - args.Player.SendMessage( - "Disabled for Server Side Inventory: " + args.Player.IgnoreActionsForInventory, - Color.Red); + args.Player.SendErrorMessage("Disabled for Server Side Inventory: " + args.Player.IgnoreActionsForInventory); } else if (TShock.Config.RequireLogin && !args.Player.IsLoggedIn) { - args.Player.SendMessage("Please /register or /login to play!", Color.Red); + args.Player.SendErrorMessage("Please /register or /login to play!"); } else if (args.Player.IgnoreActionsForClearingTrashCan) { - args.Player.SendMessage("You need to rejoin to ensure your trash can is cleared!", Color.Red); + args.Player.SendErrorMessage("You need to rejoin to ensure your trash can is cleared!"); } var lastTileX = args.Player.LastNetPosition.X; var lastTileY = args.Player.LastNetPosition.Y - 48; @@ -2299,9 +2295,8 @@ namespace TShockAPI { control[5] = false; args.Player.Disable("Using banned item"); - args.Player.SendMessage( - string.Format("You cannot use {0} on this server. Your actions are being ignored.", - args.TPlayer.inventory[item].name), Color.Red); + args.Player.SendErrorMessage("You cannot use {0} on this server. Your actions are being ignored.", + args.TPlayer.inventory[item].name); } if (args.TPlayer.inventory[item].name == "Mana Crystal" && args.Player.TPlayer.statManaMax <= 180) @@ -2419,7 +2414,7 @@ namespace TShockAPI var owner = args.Data.ReadInt8(); var type = args.Data.ReadInt16(); var bits = (BitsByte) args.Data.ReadInt8(); - owner = (byte)args.Player.Index; + owner = (byte)args.Player.Index; float[] ai = new float[Projectile.maxAI]; for (int i = 0; i < Projectile.maxAI; i++) @@ -2449,15 +2444,8 @@ namespace TShockAPI args.Player.RemoveProjectile(ident, owner); return true; } - // Server now checks owner + ident, if owner is different, server will create new projectile. - /*if (args.Player.Index != owner) - { - args.Player.Disable(String.Format("Owner ({0}) and player ID ({1}) does not match to update projectile", owner, args.Player.Index)); - args.Player.RemoveProjectile(ident, owner); - return true; - }*/ - - if (dmg > TShock.Config.MaxProjDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) + + if (dmg > TShock.Config.MaxProjDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) { args.Player.Disable(String.Format("Projectile damage is higher than {0}.", TShock.Config.MaxProjDamage)); args.Player.RemoveProjectile(ident, owner); @@ -2475,7 +2463,7 @@ namespace TShockAPI { if (type == 100 || type == 164 || type == 180 || type == 261 || (type > 289 && type < 298) || (type >= 325 && type <= 328) || (type >= 345 && type <= 352)) { - Log.Debug("Certain projectiles have been ignored for cheat detection."); + TShock.Log.Debug("Certain projectiles have been ignored for cheat detection."); } else { @@ -2502,7 +2490,7 @@ namespace TShockAPI { if (type == 90 && TShock.Config.ProjIgnoreShrapnel) // Ignore crystal shards { - Log.Debug("Ignoring shrapnel per config.."); + TShock.Log.Debug("Ignoring shrapnel per config.."); } else if (!Main.projectile[index].active) { @@ -2527,7 +2515,7 @@ namespace TShockAPI { var ident = args.Data.ReadInt16(); var owner = args.Data.ReadInt8(); - owner = (byte)args.Player.Index; + owner = (byte)args.Player.Index; var index = TShock.Utils.SearchProjectile(ident, owner); if (index > Main.maxProjectiles || index < 0) @@ -2537,7 +2525,7 @@ namespace TShockAPI var type = Main.projectile[index].type; - // Players can no longer destroy projectiles that are not theirs as of 1.1.2 + // Players can no longer destroy projectiles that are not theirs as of 1.1.2 /*if (args.Player.Index != Main.projectile[index].owner && type != 102 && type != 100 && !TShock.Config.IgnoreProjKill) // workaround for skeletron prime projectiles { args.Player.Disable(String.Format("Owner ({0}) and player ID ({1}) does not match to kill projectile of type: {3}", Main.projectile[index].owner, args.Player.Index, type)); @@ -2551,7 +2539,7 @@ namespace TShockAPI return true; } - if (TShock.CheckProjectilePermission(args.Player, index, type) && type != 102 && type != 100 && !TShock.Config.IgnoreProjKill) + if (TShock.CheckProjectilePermission(args.Player, index, type) && type != 102 && type != 100 && !TShock.Config.IgnoreProjKill) { args.Player.Disable("Does not have projectile permission to kill projectile."); args.Player.RemoveProjectile(ident, owner); @@ -2579,7 +2567,7 @@ namespace TShockAPI if (dmg > 20000) //Abnormal values have the potential to cause infinite loops in the server. { TShock.Utils.ForceKick(args.Player, "Crash Exploit Attempt", true); - Log.ConsoleError("Death Exploit Attempt: Damage {0}", dmg); + TShock.Log.ConsoleError("Death Exploit Attempt: Damage {0}", dmg); return false; } @@ -2610,18 +2598,18 @@ namespace TShockAPI } } - if (args.TPlayer.difficulty == 2 && (TShock.Config.KickOnHardcoreDeath || TShock.Config.BanOnHardcoreDeath)) - { - if (TShock.Config.BanOnHardcoreDeath) - { - if (!TShock.Utils.Ban(args.Player, TShock.Config.HardcoreBanReason, false, "hardcore-death")) - TShock.Utils.ForceKick(args.Player, "Death results in a ban, but can't ban you.", true); - } - else - { - TShock.Utils.ForceKick(args.Player, TShock.Config.HardcoreKickReason, true, false); - } - } + if (args.TPlayer.difficulty == 2 && (TShock.Config.KickOnHardcoreDeath || TShock.Config.BanOnHardcoreDeath)) + { + if (TShock.Config.BanOnHardcoreDeath) + { + if (!TShock.Utils.Ban(args.Player, TShock.Config.HardcoreBanReason, false, "hardcore-death")) + TShock.Utils.ForceKick(args.Player, "Death results in a ban, but can't ban you.", true); + } + else + { + TShock.Utils.ForceKick(args.Player, TShock.Config.HardcoreKickReason, true, false); + } + } if (args.TPlayer.difficulty == 2 && Main.ServerSideCharacter && args.Player.IsLoggedIn) { @@ -2686,32 +2674,32 @@ namespace TShockAPI } if (type == 1 && !(bucket == 2 || bucket == 0)) - { - args.Player.SendErrorMessage("You do not have permission to perform this action."); - args.Player.Disable("Spreading lava without holding a lava bucket"); - args.Player.SendTileSquare(tileX, tileY, 1); - return true; - } - - if(type == 1 && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)) - { - args.Player.SendErrorMessage("You do not have permission to perform this action."); - args.Player.Disable("Using banned lava bucket without permissions"); - args.Player.SendTileSquare(tileX, tileY, 1); - return true; - } + { + args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.Disable("Spreading lava without holding a lava bucket"); + args.Player.SendTileSquare(tileX, tileY, 1); + return true; + } + + if(type == 1 && TShock.Itembans.ItemIsBanned("Lava Bucket", args.Player)) + { + args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.Disable("Using banned lava bucket without permissions"); + args.Player.SendTileSquare(tileX, tileY, 1); + return true; + } - if (type == 0 && !(bucket == 1 || bucket == 0)) - { - args.Player.SendErrorMessage("You do not have permission to perform this action."); - args.Player.Disable("Spreading water without holding a water bucket"); - args.Player.SendTileSquare(tileX, tileY, 1); - return true; - } + if (type == 0 && !(bucket == 1 || bucket == 0)) + { + args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.Disable("Spreading water without holding a water bucket"); + args.Player.SendTileSquare(tileX, tileY, 1); + return true; + } if (type == 0 && TShock.Itembans.ItemIsBanned("Water Bucket", args.Player)) { - args.Player.SendErrorMessage("You do not have permission to perform this action."); + args.Player.SendErrorMessage("You do not have permission to perform this action."); args.Player.Disable("Using banned water bucket without permissions"); args.Player.SendTileSquare(tileX, tileY, 1); return true; @@ -2825,20 +2813,20 @@ namespace TShockAPI args.Player.InitSpawn = true; 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; 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); - } + } - else if ((Main.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); - } + } args.Player.Dead = false; return false; @@ -2970,7 +2958,7 @@ namespace TShockAPI if (!args.Player.Group.HasPermission(Permissions.movenpc)) { - args.Player.SendMessage("You do not have permission to relocate NPCs.", Color.Red); + 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)); return true; @@ -2978,13 +2966,13 @@ namespace TShockAPI if (TShock.CheckTilePermission(args.Player, x, y)) { - args.Player.SendMessage( "You do not have access to modify this area.", Color.Red); + args.Player.SendErrorMessage( "You do not have access to modify this area."); args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); return true; } - //removed until NPC Home packet actually sends their home coords. + //removed until NPC Home packet actually sends their home coords. /*if (TShock.CheckRangePermission(args.Player, x, y)) { args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, @@ -3099,7 +3087,7 @@ namespace TShockAPI 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)); + TShock.Log.ConsoleInfo("Player {0} tried to sneak {1} onto the server!", args.Player.Name, item.name); args.Player.SendData(PacketTypes.ItemDrop, "", id); return true; @@ -3214,7 +3202,7 @@ namespace TShockAPI if (Main.npc[id] == null) return true; - if (dmg > TShock.Config.MaxDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) + if (dmg > TShock.Config.MaxDamage && !args.Player.Group.HasPermission(Permissions.ignoredamagecap)) { if (TShock.Config.KickOnDamageThresholdBroken) { @@ -3382,12 +3370,12 @@ namespace TShockAPI } if (spawnboss && !args.Player.Group.HasPermission(Permissions.summonboss)) { - args.Player.SendMessage("You don't have permission to summon a boss.", Color.Red); + args.Player.SendErrorMessage("You don't have permission to summon a boss."); return true; } if (invasion && !args.Player.Group.HasPermission(Permissions.startinvasion)) { - args.Player.SendMessage("You don't have permission to start an invasion.", Color.Red); + args.Player.SendErrorMessage("You don't have permission to start an invasion."); return true; } if (!spawnboss && !invasion) diff --git a/TShockAPI/Group.cs b/TShockAPI/Group.cs index 7efcb07a..1f953dff 100644 --- a/TShockAPI/Group.cs +++ b/TShockAPI/Group.cs @@ -153,13 +153,6 @@ namespace TShockAPI public byte B = 255; public static Group DefaultGroup = null; -#if COMPAT_SIGS - [Obsolete("This constructor is for signature compatibility for external code only")] - public Group(string groupname, Group parentgroup, string chatcolor) - : this(groupname, parentgroup, chatcolor, null) - { - } -#endif public Group(string groupname, Group parentgroup = null, string chatcolor = "255,255,255", string permissions = null) { diff --git a/TShockAPI/Hooks/AccountHooks.cs b/TShockAPI/Hooks/AccountHooks.cs index e9bf76d2..8c82d0ed 100755 --- a/TShockAPI/Hooks/AccountHooks.cs +++ b/TShockAPI/Hooks/AccountHooks.cs @@ -21,7 +21,7 @@ namespace TShockAPI.Hooks { public class AccountDeleteEventArgs { - public User User { get; set; } + public User User { get; private set; } public AccountDeleteEventArgs(User user) { @@ -31,7 +31,7 @@ namespace TShockAPI.Hooks public class AccountCreateEventArgs { - public User User { get; set; } + public User User { get; private set; } public AccountCreateEventArgs(User user) { diff --git a/TShockAPI/Hooks/RegionHooks.cs b/TShockAPI/Hooks/RegionHooks.cs new file mode 100644 index 00000000..1f195925 --- /dev/null +++ b/TShockAPI/Hooks/RegionHooks.cs @@ -0,0 +1,111 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +using TShockAPI.DB; + +namespace TShockAPI.Hooks +{ + public class RegionHooks + { + public class RegionEnteredEventArgs + { + public TSPlayer Player { get; private set; } + + public RegionEnteredEventArgs(TSPlayer ply) + { + Player = ply; + } + } + + public delegate void RegionEnteredD(RegionEnteredEventArgs args); + public static event RegionEnteredD RegionEntered; + public static void OnRegionEntered(TSPlayer player) + { + if (RegionEntered == null) + { + return; + } + + RegionEntered(new RegionEnteredEventArgs(player)); + } + + public class RegionLeftEventArgs + { + public TSPlayer Player { get; private set; } + public Region Region { get; private set; } + + public RegionLeftEventArgs(TSPlayer ply, Region region) + { + Player = ply; + Region = region; + } + } + + public delegate void RegionLeftD(RegionLeftEventArgs args); + public static event RegionLeftD RegionLeft; + public static void OnRegionLeft(TSPlayer player, Region region) + { + if (RegionLeft == null) + { + return; + } + + RegionLeft(new RegionLeftEventArgs(player, region)); + } + + public class RegionCreatedEventArgs + { + public Region Region { get; private set; } + + public RegionCreatedEventArgs(Region region) + { + Region = region; + } + } + + public delegate void RegionCreatedD(RegionCreatedEventArgs args); + public static event RegionCreatedD RegionCreated; + public static void OnRegionCreated(Region region) + { + if (RegionCreated == null) + return; + + RegionCreated(new RegionCreatedEventArgs(region)); + } + + public class RegionDeletedEventArgs + { + public Region Region { get; private set; } + + public RegionDeletedEventArgs(Region region) + { + Region = region; + } + } + + public delegate void RegionDeletedD(RegionDeletedEventArgs args); + public static event RegionDeletedD RegionDeleted; + public static void OnRegionDeleted(Region region) + { + if (RegionDeleted == null) + return; + + RegionDeleted(new RegionDeletedEventArgs(region)); + } + } +} diff --git a/TShockAPI/ILog.cs b/TShockAPI/ILog.cs new file mode 100644 index 00000000..a8c65eaf --- /dev/null +++ b/TShockAPI/ILog.cs @@ -0,0 +1,153 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +using System; + +namespace TShockAPI +{ + [Flags] + public enum LogLevel + { + None = 0, + Debug = 1, + Info = 2, + Warning = 4, + Error = 8, + Data = 16, + All = 31 + } + +/// +/// Logging interface +/// + public interface ILog + { + /// + /// Log name + /// + string Name { get; } + + /// + /// Checks whether the log level contains the specified flag. + /// + /// The value to check. + bool MayWriteType(LogLevel type); + + /// + /// Writes an informative string to the log and to the console. + /// + /// The message to be written. + void ConsoleInfo(string message); + + /// + /// Writes an informative string to the log and to the console. + /// + /// The format of the message to be written. + /// The format arguments. + void ConsoleInfo(string format, params object[] args); + + /// + /// Writes an error message to the log and to the console. + /// + /// The message to be written. + void ConsoleError(string message); + + /// + /// Writes an error message to the log and to the console. + /// + /// The format of the message to be written. + /// The format arguments. + void ConsoleError(string format, params object[] args); + + /// + /// Writes a warning to the log. + /// + /// The message to be written. + void Warn(string message); + + /// + /// Writes a warning to the log. + /// + /// The format of the message to be written. + /// The format arguments. + void Warn(string format, params object[] args); + + /// + /// Writes an error to the log. + /// + /// The message to be written. + void Error(string message); + /// + /// Writes an error to the log. + /// + /// The format of the message to be written. + /// The format arguments. + void Error(string format, params object[] args); + + /// + /// Writes an informative string to the log. + /// + /// The message to be written. + void Info(string message); + + /// + /// Writes an informative string to the log. + /// + /// The format of the message to be written. + /// The format arguments. + void Info(string format, params object[] args); + + /// + /// Writes data to the log. + /// + /// The message to be written. + void Data(string message); + + /// + /// Writes data to the log. + /// + /// The format of the message to be written. + /// The format arguments. + void Data(string format, params object[] args); + + /// + /// Writes a message to the log + /// + /// Message to write + /// LogLevel assosciated with the message + void Write(string message, LogLevel level); + + /// + /// Writes a debug string to the log file. + /// + /// The message to be written. + void Debug(String message); + + /// + /// Writes a debug string to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + void Debug(string format, params object[] args); + + /// + /// Dispose the Log + /// + void Dispose(); + } +} diff --git a/TShockAPI/Log.cs b/TShockAPI/Log.cs index b2bb540f..cab2a1e4 100644 --- a/TShockAPI/Log.cs +++ b/TShockAPI/Log.cs @@ -17,57 +17,16 @@ along with this program. If not, see . */ using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; namespace TShockAPI { - [Flags] - public enum LogLevel - { - None = 0, - Debug = 1, - Info = 2, - Warning = 4, - Error = 8, - Data = 16, - All = 31 - } - public static class Log { - private static string _filename; - private static LogLevel _logLevel; - private static StreamWriter _logWriter; - - /// - /// Creates the log file stream and sets the initial log level. - /// - /// The output filename. This file will be overwritten if 'clear' is set. - /// The value which sets the type of messages to output. - /// Whether or not to clear the log file on initialization. - public static void Initialize(string filename, LogLevel logLevel, bool clear) - { - _filename = filename; - _logLevel = logLevel; - - _logWriter = new StreamWriter(filename, !clear); - } - - /// - /// Checks whether the log level contains the specified flag. - /// - /// The value to check. - private static bool MayWriteType(LogLevel type) - { - return ((_logLevel & type) == type); - } - /// /// Writes data to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.Data")] public static void Data(String message) { Write(message, LogLevel.Data); @@ -78,6 +37,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.Data")] public static void Data(string format, params object[] args) { Data(String.Format(format, args)); @@ -87,6 +47,7 @@ namespace TShockAPI /// Writes an error to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.Error")] public static void Error(String message) { Write(message, LogLevel.Error); @@ -97,6 +58,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.Error")] public static void Error(string format, params object[] args) { Error(String.Format(format, args)); @@ -106,6 +68,7 @@ namespace TShockAPI /// Writes an error to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.ConsoleError")] public static void ConsoleError(String message) { Console.ForegroundColor = ConsoleColor.Red; @@ -119,6 +82,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.ConsoleError")] public static void ConsoleError(string format, params object[] args) { ConsoleError(String.Format(format, args)); @@ -128,6 +92,7 @@ namespace TShockAPI /// Writes a warning to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.Warn")] public static void Warn(String message) { Write(message, LogLevel.Warning); @@ -138,6 +103,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.Warn")] public static void Warn(string format, params object[] args) { Warn(String.Format(format, args)); @@ -147,6 +113,7 @@ namespace TShockAPI /// Writes an informative string to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.Info")] public static void Info(String message) { Write(message, LogLevel.Info); @@ -157,6 +124,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.Info")] public static void Info(string format, params object[] args) { Info(String.Format(format, args)); @@ -166,6 +134,7 @@ namespace TShockAPI /// Writes an informative string to the log file. Also outputs to the console. /// /// The message to be written. + [Obsolete("Please use TShock.Log.ConsoleInfo")] public static void ConsoleInfo(String message) { Console.ForegroundColor = ConsoleColor.Yellow; @@ -179,6 +148,7 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.ConsoleInfo")] public static void ConsoleInfo(string format, params object[] args) { ConsoleInfo(String.Format(format, args)); @@ -188,6 +158,7 @@ namespace TShockAPI /// Writes a debug string to the log file. /// /// The message to be written. + [Obsolete("Please use TShock.Log.Debug")] public static void Debug(String message) { Write(message, LogLevel.Debug); @@ -198,53 +169,18 @@ namespace TShockAPI /// /// The format of the message to be written. /// The format arguments. + [Obsolete("Please use TShock.Log.Debug")] public static void Debug(string format, params object[] args) { Debug(String.Format(format, args)); } - /// - /// Disposes objects that are being used. - /// - public static void Dispose() - { - _logWriter.Dispose(); - } - /// /// Internal method which writes a message directly to the log file. /// private static void Write(String message, LogLevel level) { - if (!MayWriteType(level)) - { - return; - } - - string caller = "TShock"; - - StackFrame frame = new StackTrace().GetFrame(2); - if (frame != null) - { - var meth = frame.GetMethod(); - if (meth != null) - caller = meth.DeclaringType.Name; - } - - try - { - _logWriter.WriteLine(string.Format("{0} - {1}: {2}: {3}", - DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), - caller, level.ToString().ToUpper(), message)); - _logWriter.Flush(); - } - catch (ObjectDisposedException) - { - Console.WriteLine("Unable to write to log as log has been disposed."); - Console.WriteLine("{0} - {1}: {2}: {3}", - DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), - caller, level.ToString().ToUpper(), message); - } + TShock.Log.Write(message, level); } } } \ No newline at end of file diff --git a/TShockAPI/PacketBufferer.cs b/TShockAPI/PacketBufferer.cs index 051a9531..5d420618 100644 --- a/TShockAPI/PacketBufferer.cs +++ b/TShockAPI/PacketBufferer.cs @@ -145,7 +145,7 @@ namespace TShockAPI } catch (Exception e) { - Log.ConsoleError(e.ToString()); + TShock.Log.ConsoleError(e.ToString()); } return false; } @@ -206,7 +206,7 @@ namespace TShockAPI } catch (ObjectDisposedException e) { - Log.Warn(e.ToString()); + TShock.Log.Warn(e.ToString()); } catch (SocketException e) { @@ -216,7 +216,7 @@ namespace TShockAPI case 10053: break; default: - Log.Warn(e.ToString()); + TShock.Log.Warn(e.ToString()); break; } } @@ -230,12 +230,12 @@ namespace TShockAPI case SocketError.ConnectionReset: break; default: - Log.Warn(e.ToString()); + TShock.Log.Warn(e.ToString()); break; } } else - Log.Warn(e.ToString()); + TShock.Log.Warn(e.ToString()); } return false; } diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index d970182a..e9d943f3 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -349,6 +349,9 @@ namespace TShockAPI [Description("Player recovers health as damage is taken. Can be one shotted.")] public static readonly string godmode = "tshock.godmode"; + [Description("User can godmode other players")] + public static readonly string godmodeother = "tshock.godmode.other"; + [Description("Player can chat")] public static readonly string canchat = "tshock.canchat"; diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index 3333497b..32afbe74 100755 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -53,5 +53,5 @@ using System.Runtime.InteropServices; // 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.2.6")] -[assembly: AssemblyFileVersion("4.2.6")] +[assembly: AssemblyVersion("4.2.7")] +[assembly: AssemblyFileVersion("4.2.7")] diff --git a/TShockAPI/RconHandler.cs b/TShockAPI/RconHandler.cs deleted file mode 100644 index 39f32fa2..00000000 --- a/TShockAPI/RconHandler.cs +++ /dev/null @@ -1,454 +0,0 @@ -/* -TShock, a server mod for Terraria -Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Streams; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using Terraria; - -namespace TShockAPI -{ - internal class RconHandler - { - public static string Password = ""; - private static DateTime LastRequest; - private static DateTime LastHeartbeat; - public static int ListenPort; - public static bool ContinueServer = true; - public static string Response = ""; - private static bool Started; - private static UdpClient listener; - private static Thread startThread; - private static Thread heartbeat; - private static Thread listen; - - public static void ShutdownAllThreads() - { - if (Started) - { - startThread.Abort(); - heartbeat.Abort(); - listen.Abort(); - Started = false; - } - } - - public static void StartThread() - { - if (!Started) - { - startThread = new Thread(Start); - startThread.Start(); - - heartbeat = new Thread(SendHeartbeat); - heartbeat.Start(); - } - Started = true; - } - - public static void Start() - { - Log.Info("Starting RconHandler."); - try - { - Console.WriteLine(string.Format("RconHandler is running at UDP port {0} and password is {1}", - ListenPort, - Password)); - listen = new Thread(Listener); - listen.Start(); - while (true) - { - if (listen.ThreadState != ThreadState.Running) - { - listen.Abort(); - while (listen.ThreadState != ThreadState.Stopped) - continue; - listen.Start(); - } - Thread.Sleep(3000); - } - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - } - - private static void Listener() - { - if (listener == null) - try - { - listener = new UdpClient(ListenPort); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.AddressAlreadyInUse) - Log.ConsoleError("Could not bind to " + ListenPort + ". Are you sure you don't have another instance running?"); - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - while (ContinueServer) - { - try - { - var listenEP = new IPEndPoint(IPAddress.Any, ListenPort); - LastRequest = DateTime.Now; - byte[] bytes = listener.Receive(ref listenEP); - var packet = ParsePacket(bytes, listenEP); - listener.Send(packet, packet.Length, listenEP); - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - } - } - - private static string SendPacket(byte[] bytes, string hostname, int port) - { - var response = Encoding.UTF8.GetString(new byte[] {0xFF, 0xFF, 0xFF, 0xFF}) + "disconnect"; - try - { - var EP = new IPEndPoint(IPAddress.Any, port); - using (var client = new UdpClient()) - { - client.Connect(hostname, port); - client.Client.ReceiveTimeout = 500; - client.Send(bytes, bytes.Length); - response = Encoding.UTF8.GetString(client.Receive(ref EP)); - } - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - return response; - } - - private static byte[] ParsePacket(byte[] bytes, IPEndPoint EP) - { - string response = ""; - var packetstring = Encoding.UTF8.GetString(PadPacket(bytes)); - var redirect = false; - var print = true; - if ((DateTime.Now - LastRequest).Milliseconds >= 100) - { - if (packetstring.StartsWith("rcon") || packetstring.Substring(4).StartsWith("rcon") || - packetstring.Substring(5).StartsWith("rcon")) - { - if (!string.IsNullOrEmpty(Password)) - { - var args = ParseParameters(packetstring); - if (args.Count >= 3) - { - if (args[1] == Password) - { - args[1] = args[0] = ""; - string command = string.Join(" ", args.ToArray()); - command = command.TrimEnd(' ').TrimEnd('\0').TrimStart(' '); - Log.ConsoleInfo("Rcon from " + EP + ":" + command); - Response = ""; - response = ExecuteCommand(command); - response += "\n" + Response; - Response = ""; - response = response.TrimStart('\n'); - } - else - { - response = "Bad rcon password.\n"; - Log.ConsoleInfo("Bad rcon password from " + EP); - } - } - else - response = ""; - } - else - { - response = "No rcon password set on the server.\n"; - Log.Info("No password for rcon set"); - } - } - else - redirect = true; - } - if (packetstring.StartsWith("getinfo") - || packetstring.Substring(4).StartsWith("getinfo") - || packetstring.Substring(5).StartsWith("getinfo")) - { - var challenge = ""; - if (packetstring.Split(' ').Length == 2) - challenge = packetstring.Split(' ')[1]; - response = "infoResponse\n"; - var infostring = - string.Format( - @"\_TShock_ver\{6}\mapname\{1}\sv_maxclients\{2}\clients\{3}\sv_privateClients\{4}\hconly\{5}\gamename\TERRARIA\protocol\100\sv_hostname\{0}\g_needPass\{7}", - TShock.Config.ServerName, Main.worldName, Main.maxNetPlayers, - TShock.Utils.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, - TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum, - Netplay.password != "" ? 1 : 0); - if (challenge != "") - infostring += @"\challenge\" + challenge; - response += infostring; - print = false; - redirect = false; - } - else if (packetstring.StartsWith("getstatus") - || packetstring.Substring(4).StartsWith("getstatus") - || packetstring.Substring(5).StartsWith("getstatus")) - { - var challenge = ""; - if (packetstring.Split(' ').Length == 2) - challenge = packetstring.Split(' ')[1]; - response = "statusResponse\n"; - var statusstring = string.Format( - @"\_TShock_ver\{6}\mapname\{1}\sv_maxclients\{2}\clients\{3}\sv_privateClients\{4}\hconly\{5}\gamename\TERRARIA\protocol\100\sv_hostname\{0}\g_needPass\{7}", - TShock.Config.ServerName, Main.worldName, Main.maxNetPlayers, - TShock.Utils.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, - TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum, - Netplay.password != "" ? 1 : 0) + "\n"; - if (challenge != "") - statusstring += @"\challenge\" + challenge; - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - statusstring += (string.Format("0 0 {0}\n", player.Name)); - } - response += statusstring; - print = false; - redirect = false; - } - if (!redirect) - return (ConstructPacket(response, print)); - else - return (ConstructPacket("disconnect", false)); - } - - private static string ExecuteCommand(string text) - { - if (Main.rand == null) - Main.rand = new Random(); - if (WorldGen.genRand == null) - WorldGen.genRand = new Random(); - if (text.StartsWith("exit")) - { - TShock.Utils.StopServer(); - return "Server shutting down."; - } - else if (text.StartsWith("playing") || text.StartsWith("/playing")) - { - int count = 0; - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - count++; - TSPlayer.Server.SendMessage(string.Format("{0} ({1}) [{2}] <{3}>", player.Name, player.IP, player.Group.Name, - player.UserAccountName)); - } - } - TSPlayer.Server.SendMessage(string.Format("{0} players connected.", count)); - } - else if (text.StartsWith("status")) - { - Response += "map: " + Main.worldName + "\n"; - Response += "num score ping name lastmsg address qport rate\n"; - int count = 0; - foreach (TSPlayer player in TShock.Players) - { - if (player != null && player.Active) - { - count++; - Response += - (string.Format("{0} 0 0 {1}({2}) {3} {4} 0 0", count, player.Name, player.Group.Name, - Netplay.serverSock[player.Index].tcpClient.Client.RemoteEndPoint, "")) + "\n"; - } - } - } - else if (text.StartsWith("say ")) - { - Log.Info(string.Format("Server said: {0}", text.Remove(0, 4))); - return string.Format("Server said: {0}", text.Remove(0, 4)); - } - else if (text == "autosave") - { - Main.autoSave = TShock.Config.AutoSave = !TShock.Config.AutoSave; - Log.ConsoleInfo("AutoSave " + (TShock.Config.AutoSave ? "Enabled" : "Disabled")); - return "AutoSave " + (TShock.Config.AutoSave ? "Enabled" : "Disabled"); - } - else if (text.StartsWith("/")) - { - if (!Commands.HandleCommand(TSPlayer.Server, text)) - return "Invalid command."; - } - else if (!Commands.HandleCommand(TSPlayer.Server, "/" + text)) - return "Invalid command."; - return ""; - } - - private static byte[] ConstructPacket(string response, bool print) - { - var oob = new byte[] {0xFF, 0xFF, 0xFF, 0xFF}; - using (var stream = new MemoryStream()) - { - stream.WriteBytes(oob); - if (print) - stream.WriteBytes(Encoding.UTF8.GetBytes(string.Format("print\n{0}", response))); - else - stream.WriteBytes(Encoding.UTF8.GetBytes(response)); - var trimmedpacket = new byte[(int) stream.Length]; - var packet = stream.GetBuffer(); - Array.Copy(packet, trimmedpacket, (int) stream.Length); - return trimmedpacket; - } - } - - private static byte[] PadPacket(byte[] packet) - { - var returnpacket = new byte[(4 + packet.Length)]; - int h = 0; - if (packet[0] != 0xFF) - { - for (int i = 0; i < 4; i++) - returnpacket[i] = 0xFF; - for (int i = 4; i < returnpacket.Length; i++) - returnpacket[i] = packet[h++]; - } - else - returnpacket = packet; - return returnpacket; - } - - private static void SendHeartbeat() - { - LastHeartbeat = DateTime.UtcNow.Subtract(new TimeSpan(0, 0, 30)); - while (true) - { - if ((DateTime.UtcNow - LastHeartbeat).Seconds >= 30) - { - var packet = ConstructPacket("heartbeat TerrariaShock", false); - if (listener == null) - try - { - listener = new UdpClient(ListenPort); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.AddressAlreadyInUse) - Log.ConsoleError("Could not bind to " + ListenPort + ". Are you sure you don't have another instance running?"); - } - catch (Exception e) - { - Log.Error(e.ToString()); - } - listener.Send(packet, packet.Length, TShock.Config.MasterServer, 27950); - LastHeartbeat = DateTime.UtcNow; - } - Thread.Sleep(10000); - } - } - - #region ParseParams - - private static List ParseParameters(string str) - { - var ret = new List(); - var sb = new StringBuilder(); - bool instr = false; - for (int i = 0; i < str.Length; i++) - { - char c = str[i]; - - if (instr) - { - if (c == '\\') - { - if (i + 1 >= str.Length) - break; - c = GetEscape(str[++i]); - } - else if (c == '"') - { - ret.Add(sb.ToString()); - sb.Clear(); - instr = false; - continue; - } - sb.Append(c); - } - else - { - if (IsWhiteSpace(c)) - { - if (sb.Length > 0) - { - ret.Add(sb.ToString()); - sb.Clear(); - } - } - else if (c == '"') - { - if (sb.Length > 0) - { - ret.Add(sb.ToString()); - sb.Clear(); - } - instr = true; - } - else - { - sb.Append(c); - } - } - } - if (sb.Length > 0) - ret.Add(sb.ToString()); - - return ret; - } - - private static char GetEscape(char c) - { - switch (c) - { - case '\\': - return '\\'; - case '"': - return '"'; - case 't': - return '\t'; - default: - return c; - } - } - - private static bool IsWhiteSpace(char c) - { - return c == ' ' || c == '\t' || c == '\n'; - } - - #endregion - } -} \ No newline at end of file diff --git a/TShockAPI/Rest/Rest.cs b/TShockAPI/Rest/Rest.cs index 4fbf94e4..a5e77115 100644 --- a/TShockAPI/Rest/Rest.cs +++ b/TShockAPI/Rest/Rest.cs @@ -157,7 +157,8 @@ namespace Rests e.Response.Connection.Type = ConnectionType.Close; e.Response.ContentType = new ContentTypeHeader("application/json; charset=utf-8"); e.Response.Add(serverHeader); - e.Response.Body.Write(Encoding.UTF8.GetBytes(str), 0, str.Length); + var bytes = Encoding.UTF8.GetBytes(str); + e.Response.Body.Write(bytes, 0, bytes.Length); e.Response.Status = HttpStatusCode.OK; } @@ -212,7 +213,7 @@ namespace Rests object result = cmd.Execute(verbs, parms, request); if (cmd.DoLog && TShock.Config.LogRest) { - Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false)); + TShock.Log.ConsoleInfo("Anonymous requested REST endpoint: " + BuildRequestUri(cmd, verbs, parms, false)); } return result; diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index 93d81eee..5acf24e8 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -179,7 +179,7 @@ namespace TShockAPI var msg = args.Parameters["msg"]; if (string.IsNullOrWhiteSpace(msg)) return RestMissingParam("msg"); - TShock.Utils.Broadcast(msg); + TSPlayer.All.SendInfoMessage(msg); return RestResponse("The message was broadcasted successfully"); } @@ -660,7 +660,7 @@ namespace TShockAPI TSPlayer player = (TSPlayer)ret; player.DamagePlayer(999999); var from = string.IsNullOrWhiteSpace(args.Parameters["from"]) ? "Server Admin" : args.Parameters["from"]; - player.SendMessage(string.Format("{0} just killed you!", from)); + player.SendInfoMessage(string.Format("{0} just killed you!", from)); return RestResponse("Player " + player.Name + " was killed"); } @@ -916,7 +916,7 @@ namespace TShockAPI TSPlayer player = (TSPlayer)ret; player.mute = mute; var verb = mute ? "muted" : "unmuted"; - player.SendMessage("You have been remotely " + verb); + player.SendInfoMessage("You have been remotely " + verb); return RestResponse("Player " + player.Name + " was " + verb); } diff --git a/TShockAPI/Rest/SecureRest.cs b/TShockAPI/Rest/SecureRest.cs index ee9eac2f..0913a87d 100644 --- a/TShockAPI/Rest/SecureRest.cs +++ b/TShockAPI/Rest/SecureRest.cs @@ -68,7 +68,7 @@ namespace Rests "The old model will be removed with the next maintenance release of TShock. In order to switch to the new model, ", "change the config setting \"RestUseNewPermissionModel\" to true." ); - Log.Warn(warningMessage); + TShock.Log.Warn(warningMessage); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(warningMessage); Console.ForegroundColor = ConsoleColor.Gray; @@ -80,7 +80,7 @@ namespace Rests "with existing REST services. If compatibility problems occur, you can switch back to the unsecure permission ", "model by changing the config setting \"RestUseNewPermissionModel\" to false, which is not recommended." ); - Log.ConsoleInfo(warningMessage); + TShock.Log.ConsoleInfo(warningMessage); } } diff --git a/TShockAPI/SaveManager.cs b/TShockAPI/SaveManager.cs index 0557183d..08ee376a 100644 --- a/TShockAPI/SaveManager.cs +++ b/TShockAPI/SaveManager.cs @@ -58,8 +58,8 @@ namespace TShockAPI } catch (Exception ex) { - Log.Error("World saved notification failed"); - Log.Error(ex.ToString()); + TShock.Log.Error("World saved notification failed"); + TShock.Log.Error(ex.ToString()); } } } @@ -130,12 +130,12 @@ namespace TShockAPI else WorldFile.saveWorld(task.resetTime); TShock.Utils.Broadcast("World saved.", Color.Yellow); - Log.Info(string.Format("World saved at ({0})", Main.worldPathName)); + TShock.Log.Info(string.Format("World saved at ({0})", Main.worldPathName)); } catch (Exception e) { - Log.Error("World saved failed"); - Log.Error(e.ToString()); + TShock.Log.Error("World saved failed"); + TShock.Log.Error(e.ToString()); } } } diff --git a/TShockAPI/SqlLog.cs b/TShockAPI/SqlLog.cs new file mode 100644 index 00000000..bb3987c0 --- /dev/null +++ b/TShockAPI/SqlLog.cs @@ -0,0 +1,295 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using TShockAPI.DB; + +namespace TShockAPI +{ + struct LogInfo + { + public string timestamp; + public string message; + public string caller; + public LogLevel logLevel; + + public override string ToString() + { + return String.Format("Message: {0}: {1}: {2}", + caller, logLevel.ToString().ToUpper(), message); + } + } + + /// + /// Class inheriting ILog for writing logs to TShock's SQL database + /// + public class SqlLog : ILog, IDisposable + { + private readonly LogLevel _logLevel; + private readonly IDbConnection _database; + private readonly TextLog _backupLog; + private readonly List _failures = new List(TShock.Config.RevertToTextLogsOnSqlFailures); + private bool _useTextLog; + + public string Name + { + get { return "SQL Log Writer"; } + } + + public SqlLog(LogLevel logLevel, IDbConnection db, string textlogFilepath, bool clearTextLog) + { + _logLevel = logLevel; + _database = db; + _backupLog = new TextLog(textlogFilepath, logLevel, clearTextLog); + } + + public bool MayWriteType(LogLevel type) + { + return ((_logLevel & type) == type); + } + + /// + /// Writes data to the log file. + /// + /// The message to be written. + public void Data(String message) + { + Write(message, LogLevel.Data); + } + + /// + /// Writes data to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void Data(string format, params object[] args) + { + Data(String.Format(format, args)); + } + + /// + /// Writes an error to the log file. + /// + /// The message to be written. + public void Error(String message) + { + Write(message, LogLevel.Error); + } + + /// + /// Writes an error to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void Error(string format, params object[] args) + { + Error(String.Format(format, args)); + } + + /// + /// Writes an error to the log file. + /// + /// The message to be written. + public void ConsoleError(String message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(message); + Console.ForegroundColor = ConsoleColor.Gray; + Write(message, LogLevel.Error); + } + + /// + /// Writes an error to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void ConsoleError(string format, params object[] args) + { + ConsoleError(String.Format(format, args)); + } + + /// + /// Writes a warning to the log file. + /// + /// The message to be written. + public void Warn(String message) + { + Write(message, LogLevel.Warning); + } + + /// + /// Writes a warning to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void Warn(string format, params object[] args) + { + Warn(String.Format(format, args)); + } + + /// + /// Writes an informative string to the log file. + /// + /// The message to be written. + public void Info(String message) + { + Write(message, LogLevel.Info); + } + + /// + /// Writes an informative string to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void Info(string format, params object[] args) + { + Info(String.Format(format, args)); + } + + /// + /// Writes an informative string to the log file. Also outputs to the console. + /// + /// The message to be written. + public void ConsoleInfo(String message) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(message); + Console.ForegroundColor = ConsoleColor.Gray; + Write(message, LogLevel.Info); + } + + /// + /// Writes an informative string to the log file. Also outputs to the console. + /// + /// The format of the message to be written. + /// The format arguments. + public void ConsoleInfo(string format, params object[] args) + { + ConsoleInfo(String.Format(format, args)); + } + + /// + /// Writes a debug string to the log file. + /// + /// The message to be written. + public void Debug(String message) + { + Write(message, LogLevel.Debug); + } + + /// + /// Writes a debug string to the log file. + /// + /// The format of the message to be written. + /// The format arguments. + public void Debug(string format, params object[] args) + { + Debug(String.Format(format, args)); + } + + public void Write(string message, LogLevel level) + { + if (!MayWriteType(level)) + return; + + var caller = "TShock"; + + var frame = new StackTrace().GetFrame(2); + if (frame != null) + { + var meth = frame.GetMethod(); + if (meth != null && meth.DeclaringType != null) + caller = meth.DeclaringType.Name; + } + + try + { + if (_useTextLog) + { + _backupLog.Write(message, level); + return; + } + + _database.Query("INSERT INTO Logs (LogLevel, TimeStamp, Caller, Message) VALUES (@0, @1, @2, @3)", + level, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture), + caller, message); + + var success = true; + while (_failures.Count > 0 && success) + { + var info = _failures.First(); + + try + { + _database.Query("INSERT INTO Logs (LogLevel, TimeStamp, Caller, Message) VALUES (@0, @1, @2, @3)", + info.logLevel, info.timestamp, info.caller, info.message); + } + catch (Exception ex) + { + success = false; + _failures.Add(new LogInfo + { + caller = "TShock", + logLevel = LogLevel.Error, + message = String.Format("SQL Log insert query failed: {0}", ex), + timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) + }); + } + + if (success) + _failures.RemoveAt(0); + } + } + catch (Exception ex) + { + _backupLog.ConsoleError("SQL Log insert query failed: {0}", ex); + + _failures.Add(new LogInfo + { + logLevel = level, + message = message, + caller = caller, + timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) + }); + } + + if (_failures.Count >= TShock.Config.RevertToTextLogsOnSqlFailures) + { + _useTextLog = true; + _backupLog.ConsoleError("SQL Logging disabled due to errors. Reverting to text logging."); + + foreach(var logInfo in _failures) + { + _backupLog.Write(String.Format("SQL log failed at: {0}. {1}", logInfo.timestamp, logInfo), + LogLevel.Error); + } + _failures.Clear(); + } + } + + public void Dispose() + { + _backupLog.Dispose(); + } + } +} \ No newline at end of file diff --git a/TShockAPI/StatTracker.cs b/TShockAPI/StatTracker.cs old mode 100644 new mode 100755 index d8f422c5..3850f48c --- a/TShockAPI/StatTracker.cs +++ b/TShockAPI/StatTracker.cs @@ -45,7 +45,7 @@ namespace TShockAPI var serialized = Newtonsoft.Json.JsonConvert.SerializeObject(data); var encoded = HttpUtility.UrlEncode(serialized); - var uri = String.Format("http://96.47.231.227:8000?data={0}", encoded); + var uri = String.Format("http://stats.tshock.co/publish/{0}", encoded); var client = (HttpWebRequest)WebRequest.Create(uri); client.Timeout = 5000; try @@ -64,7 +64,7 @@ namespace TShockAPI { if (!failed) { - Log.ConsoleError("StatTracker Exception: {0}", e); + TShock.Log.ConsoleError("StatTracker Exception: {0}", e); failed = true; } } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 3c711431..17fa8667 100755 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -30,29 +30,29 @@ namespace TShockAPI { public class TSPlayer { - /// - /// This represents the server as a player. - /// + /// + /// This represents the server as a player. + /// public static readonly TSServerPlayer Server = new TSServerPlayer(); - /// - /// This player represents all the players. - /// + /// + /// This player represents all the players. + /// public static readonly TSPlayer All = new TSPlayer("All"); - /// - /// The amount of tiles that the player has killed in the last second. - /// + /// + /// The amount of tiles that the player has killed in the last second. + /// public int TileKillThreshold { get; set; } - /// - /// The amount of tiles the player has placed in the last second. - /// - public int TilePlaceThreshold { get; set; } + /// + /// The amount of tiles the player has placed in the last second. + /// + public int TilePlaceThreshold { get; set; } - /// - /// The amount of liquid (in tiles) that the player has placed in the last second. - /// + /// + /// The amount of liquid (in tiles) that the player has placed in the last second. + /// public int TileLiquidThreshold { get; set; } /// @@ -60,9 +60,9 @@ namespace TShockAPI /// public int PaintThreshold { get; set; } - /// - /// The number of projectiles created by the player in the last second. - /// + /// + /// The number of projectiles created by the player in the last second. + /// public int ProjectileThreshold { get; set; } /// @@ -83,130 +83,130 @@ namespace TShockAPI public int sX = -1; public int sY = -1; - /// - /// A queue of tiles destroyed by the player for reverting. - /// + /// + /// A queue of tiles destroyed by the player for reverting. + /// public Dictionary TilesDestroyed { get; protected set; } - /// - /// A queue of tiles placed by the player for reverting. - /// + /// + /// A queue of tiles placed by the player for reverting. + /// public Dictionary TilesCreated { get; protected set; } - /// - /// The player's group. - /// - public Group Group - { - get - { - if (tempGroup != null) - return tempGroup; - return group; - } - set { group = value; } - } + /// + /// The player's group. + /// + public Group Group + { + get + { + if (tempGroup != null) + return tempGroup; + return group; + } + set { group = value; } + } - /// - /// The player's temporary group. This overrides the user's actual group. - /// - public Group tempGroup = null; + /// + /// The player's temporary group. This overrides the user's actual group. + /// + public Group tempGroup = null; - private Group group = null; + private Group group = null; public bool ReceivedInfo { get; set; } - /// - /// The players index in the player array( Main.players[] ). - /// + /// + /// The players index in the player array( Main.players[] ). + /// public int Index { get; protected set; } - /// - /// The last time the player changed their team or pvp status. - /// + /// + /// The last time the player changed their team or pvp status. + /// public DateTime LastPvPTeamChange; - /// - /// Temp points for use in regions and other plugins. - /// + /// + /// Temp points for use in regions and other plugins. + /// public Point[] TempPoints = new Point[2]; - /// - /// Whether the player is waiting to place/break a tile to set as a temp point. - /// + /// + /// Whether the player is waiting to place/break a tile to set as a temp point. + /// public int AwaitingTempPoint { get; set; } - /// - /// A list of command callbacks indexed by the command they need to do. - /// - public Dictionary> AwaitingResponse; + /// + /// A list of command callbacks indexed by the command they need to do. + /// + public Dictionary> AwaitingResponse; public bool AwaitingName { get; set; } public string[] AwaitingNameParameters { get; set; } - /// - /// The last time a player broke a grief check. - /// + /// + /// The last time a player broke a grief check. + /// public DateTime LastThreat { get; set; } public bool InitSpawn; - /// - /// Whether the player should see logs. - /// + /// + /// Whether the player should see logs. + /// public bool DisplayLogs = true; - /// - /// The last player that the player whispered with (to or from). - /// + /// + /// The last player that the player whispered with (to or from). + /// public TSPlayer LastWhisper; - /// - /// The number of unsuccessful login attempts. - /// + /// + /// The number of unsuccessful login attempts. + /// public int LoginAttempts { get; set; } public Vector2 TeleportCoords = new Vector2(-1, -1); public Vector2 LastNetPosition = Vector2.Zero; - /// - /// The player's login name. - /// + /// + /// The player's login name. + /// public string UserAccountName { get; set; } - /// - /// Whether the player performed a valid login attempt (i.e. entered valid user name and password) but is still blocked - /// from logging in because of SSI. - /// + /// + /// Whether the player performed a valid login attempt (i.e. entered valid user name and password) but is still blocked + /// from logging in because of SSI. + /// public bool LoginFailsBySsi { get; set; } - /// - /// Whether the player is logged in or not. - /// + /// + /// Whether the player is logged in or not. + /// public bool IsLoggedIn; - /// - /// Whether the player has sent their whole inventory to the server while connecting. - /// + /// + /// Whether the player has sent their whole inventory to the server while connecting. + /// public bool HasSentInventory { get; set; } - /// - /// The player's user id( from the db ). - /// + /// + /// The player's user id( from the db ). + /// public int UserID = -1; - /// - /// Whether the player has been nagged about logging in. - /// + /// + /// Whether the player has been nagged about logging in. + /// public bool HasBeenNaggedAboutLoggingIn; - public bool TPAllow = true; + public bool TPAllow = true; - /// - /// Whether the player is muted or not. - /// + /// + /// Whether the player is muted or not. + /// public bool mute; private Player FakePlayer; @@ -218,16 +218,16 @@ namespace TShockAPI /// public int RespawnTimer; - /// - /// Whether the player is dead or not. - /// + /// + /// Whether the player is dead or not. + /// public bool Dead; public string Country = "??"; - /// - /// The players difficulty( normal[softcore], mediumcore, hardcore ). - /// + /// + /// The players difficulty( normal[softcore], mediumcore, hardcore ). + /// public int Difficulty; private string CacheIP; @@ -240,53 +240,53 @@ namespace TShockAPI public bool IgnoreActionsForClearingTrashCan; - /// - /// The player's server side inventory data. - /// + /// + /// The player's server side inventory data. + /// public PlayerData PlayerData; - /// - /// Whether the player needs to specify a password upon connection( either server or user account ). - /// + /// + /// Whether the player needs to specify a password upon connection( either server or user account ). + /// public bool RequiresPassword; public bool SilentKickInProgress; public bool SilentJoinInProgress; - /// - /// A list of points where ice tiles have been placed. - /// + /// + /// A list of points where ice tiles have been placed. + /// public List IceTiles; - /// - /// Unused, can be removed. - /// - public long RPm = 1; + /// + /// Unused, can be removed. + /// + public long RPm = 1; - /// - /// World protection message cool down. - /// - public long WPm = 1; + /// + /// World protection message cool down. + /// + public long WPm = 1; - /// - /// Spawn protection message cool down. - /// - public long SPm = 1; - - /// - /// Permission to build message cool down. - /// - public long BPm = 1; + /// + /// Spawn protection message cool down. + /// + public long SPm = 1; + + /// + /// Permission to build message cool down. + /// + public long BPm = 1; - /// - /// The time in ms when the player has logged in. - /// + /// + /// The time in ms when the player has logged in. + /// public long LoginMS; - /// - /// Whether the player has been harrassed about logging in due to server side inventory or forced login. - /// + /// + /// Whether the player has been harrassed about logging in due to server side inventory or forced login. + /// public bool LoginHarassed = false; /// @@ -303,10 +303,15 @@ namespace TShockAPI /// The last projectile type this player tried to kill. /// public int LastKilledProjectile = 0; + + /// + /// The current region this player is in, or null if none. + /// + public Region CurrentRegion = null; - /// - /// Whether the player is a real, human, player on the server. - /// + /// + /// Whether the player is a real, human, player on the server. + /// public bool RealPlayer { get { return Index >= 0 && Index < Main.maxNetPlayers && Main.player[Index] != null; } @@ -317,7 +322,7 @@ namespace TShockAPI get { return RealPlayer && - (Netplay.serverSock[Index] != null && Netplay.serverSock[Index].active && !Netplay.serverSock[Index].kill); + (Netplay.serverSock[Index] != null && Netplay.serverSock[Index].active && !Netplay.serverSock[Index].kill); } } @@ -372,28 +377,28 @@ namespace TShockAPI } } - /// - /// Saves the player's inventory to SSI - /// - /// bool - True/false if it saved successfully - public bool SaveServerCharacter() - { - if (!Main.ServerSideCharacter) - { - return false; - } - try - { - PlayerData.CopyCharacter(this); - TShock.CharacterDB.InsertPlayerData(this); - return true; - } catch (Exception e) - { - Log.Error(e.Message); - return false; - } - - } + /// + /// Saves the player's inventory to SSI + /// + /// bool - True/false if it saved successfully + public bool SaveServerCharacter() + { + if (!Main.ServerSideCharacter) + { + return false; + } + try + { + PlayerData.CopyCharacter(this); + TShock.CharacterDB.InsertPlayerData(this); + return true; + } + catch (Exception e) + { + TShock.Log.Error(e.Message); + return false; + } + } /// /// Sends the players server side character to client @@ -412,7 +417,7 @@ namespace TShockAPI } catch (Exception e) { - Log.Error(e.Message); + TShock.Log.Error(e.Message); return false; } @@ -488,9 +493,9 @@ namespace TShockAPI TilesDestroyed = new Dictionary(); TilesCreated = new Dictionary(); Index = index; - Group = Group.DefaultGroup; + Group = Group.DefaultGroup; IceTiles = new List(); - AwaitingResponse = new Dictionary>(); + AwaitingResponse = new Dictionary>(); } protected TSPlayer(String playerName) @@ -499,8 +504,8 @@ namespace TShockAPI TilesCreated = new Dictionary(); Index = -1; FakePlayer = new Player {name = playerName, whoAmi = -1}; - Group = Group.DefaultGroup; - AwaitingResponse = new Dictionary>(); + Group = Group.DefaultGroup; + AwaitingResponse = new Dictionary>(); } public virtual void Disconnect(string reason) @@ -622,7 +627,6 @@ namespace TShockAPI public void Spawn() { -// TPlayer.FindSpawn(); if (this.sX > 0 && this.sY > 0) { Spawn(this.sX, this.sY); @@ -662,8 +666,8 @@ namespace TShockAPI } } - public virtual bool SendTileSquare(int x, int y, int size = 10) - { + public virtual bool SendTileSquare(int x, int y, int size = 10) + { try { int num = (size - 1)/2; @@ -707,22 +711,22 @@ namespace TShockAPI } catch (Exception ex) { - Log.Error(ex.ToString()); + TShock.Log.Error(ex.ToString()); } return false; - } + } - public bool GiveItemCheck(int type, string name, int width, int height, int stack, int prefix = 0) - { - if ((TShock.Itembans.ItemIsBanned(name) && TShock.Config.PreventBannedItemSpawn) && - (TShock.Itembans.ItemIsBanned(name, this) || !TShock.Config.AllowAllowedGroupsToSpawnBannedItems)) - return false; + public bool GiveItemCheck(int type, string name, int width, int height, int stack, int prefix = 0) + { + if ((TShock.Itembans.ItemIsBanned(name) && TShock.Config.PreventBannedItemSpawn) && + (TShock.Itembans.ItemIsBanned(name, this) || !TShock.Config.AllowAllowedGroupsToSpawnBannedItems)) + return false; - GiveItem(type,name,width,height,stack,prefix); - return true; - } + GiveItem(type,name,width,height,stack,prefix); + return true; + } - public virtual void GiveItem(int type, string name, int width, int height, int stack, int prefix = 0) + public virtual void GiveItem(int type, string name, int width, int height, int stack, int prefix = 0) { int itemid = Item.NewItem((int) X, (int) Y, width, height, type, stack, true, prefix, true); @@ -730,7 +734,7 @@ namespace TShockAPI Main.item[itemid].SetDefaults(name); // The set default overrides the wet and stack set by NewItem Main.item[itemid].wet = Collision.WetCollision(Main.item[itemid].position, Main.item[itemid].width, - Main.item[itemid].height); + Main.item[itemid].height); Main.item[itemid].stack = stack; Main.item[itemid].owner = Index; Main.item[itemid].prefix = (byte) prefix; @@ -740,50 +744,44 @@ namespace TShockAPI NetMessage.SendData((int)PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f); } - public virtual void SendInfoMessage(string msg) - { - SendMessage(msg, Color.Yellow); - } - - public void SendInfoMessage(string format, params object[] args) - { - SendInfoMessage(string.Format(format, args)); - } - - public virtual void SendSuccessMessage(string msg) - { - SendMessage(msg, Color.Green); - } - - public void SendSuccessMessage(string format, params object[] args) - { - SendSuccessMessage(string.Format(format, args)); - } - - public virtual void SendWarningMessage(string msg) - { - SendMessage(msg, Color.OrangeRed); - } - - public void SendWarningMessage(string format, params object[] args) - { - SendWarningMessage(string.Format(format, args)); - } - - public virtual void SendErrorMessage(string msg) - { - SendMessage(msg, Color.Red); - } - - public void SendErrorMessage(string format, params object[] args) - { - SendErrorMessage(string.Format(format, args)); - } - - [Obsolete("Use SendErrorMessage, SendInfoMessage, or SendWarningMessage, or a custom color instead.")] - public virtual void SendMessage(string msg) + public virtual void SendInfoMessage(string msg) { - SendMessage(msg, 0, 255, 0); + SendMessage(msg, Color.Yellow); + } + + public void SendInfoMessage(string format, params object[] args) + { + SendInfoMessage(string.Format(format, args)); + } + + public virtual void SendSuccessMessage(string msg) + { + SendMessage(msg, Color.Green); + } + + public void SendSuccessMessage(string format, params object[] args) + { + SendSuccessMessage(string.Format(format, args)); + } + + public virtual void SendWarningMessage(string msg) + { + SendMessage(msg, Color.OrangeRed); + } + + public void SendWarningMessage(string format, params object[] args) + { + SendWarningMessage(string.Format(format, args)); + } + + public virtual void SendErrorMessage(string msg) + { + SendMessage(msg, Color.Red); + } + + public void SendErrorMessage(string format, params object[] args) + { + SendErrorMessage(string.Format(format, args)); } public virtual void SendMessage(string msg, Color color) @@ -796,10 +794,10 @@ namespace TShockAPI SendData(PacketTypes.ChatText, msg, 255, red, green, blue); } - public virtual void SendMessageFromPlayer(string msg, byte red, byte green, byte blue, int ply) - { - SendDataFromPlayer(PacketTypes.ChatText, ply, msg, red, green, blue, 0); - } + public virtual void SendMessageFromPlayer(string msg, byte red, byte green, byte blue, int ply) + { + SendDataFromPlayer(PacketTypes.ChatText, ply, msg, red, green, blue, 0); + } public virtual void DamagePlayer(int damage) { @@ -836,11 +834,11 @@ namespace TShockAPI { if (displayConsole) { - Log.ConsoleInfo(string.Format("Player {0} has been disabled for {1}.", Name, reason)); + TShock.Log.ConsoleInfo("Player {0} has been disabled for {1}.", Name, reason); } else { - Log.Info("Player {0} has been disabled for {1}.", Name, reason); + TShock.Log.Info("Player {0} has been disabled for {1}.", Name, reason); } LastDisableNotification = DateTime.UtcNow; } @@ -849,7 +847,7 @@ namespace TShockAPI StackFrame frame = null; frame = trace.GetFrame(1); if (frame != null && frame.GetMethod().DeclaringType != null) - Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable()."); + TShock.Log.Debug(frame.GetMethod().DeclaringType.Name + " called Disable()."); } public virtual void Whoopie(object time) @@ -857,7 +855,7 @@ namespace TShockAPI var time2 = (int) time; var launch = DateTime.UtcNow; var startname = Name; - SendMessage("You are now being annoyed.", Color.Red); + SendInfoMessage("You are now being annoyed."); while ((DateTime.UtcNow - launch).TotalSeconds < time2 && startname == Name) { SendData(PacketTypes.NpcSpecial, number: Index, number2: 2f); @@ -883,13 +881,13 @@ namespace TShockAPI NetMessage.SendData((int) msgType, Index, -1, text, number, number2, number3, number4, number5); } - public virtual void SendDataFromPlayer(PacketTypes msgType, int ply, string text = "", float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0) - { - if (RealPlayer && !ConnectionAlive) - return; + public virtual void SendDataFromPlayer(PacketTypes msgType, int ply, string text = "", float number2 = 0f, float number3 = 0f, float number4 = 0f, int number5 = 0) + { + if (RealPlayer && !ConnectionAlive) + return; - NetMessage.SendData((int) msgType, Index, -1, text, ply, number2, number3, number4, number5); - } + NetMessage.SendData((int) msgType, Index, -1, text, ply, number2, number3, number4, number5); + } public virtual void SendRawData(byte[] data) { @@ -898,20 +896,20 @@ namespace TShockAPI NetMessage.SendBytes(Netplay.serverSock[Index], data, 0, data.Length, Netplay.serverSock[Index].ServerWriteCallBack, Netplay.serverSock[Index].networkStream); } - /// - /// Adds a command callback to a specified command string. - /// - /// The string representing the command i.e "yes" == /yes - /// The method that will be executed on confirmation ie user accepts - public void AddResponse( string name, Action callback) - { - if( AwaitingResponse.ContainsKey(name)) - { - AwaitingResponse.Remove(name); - } + /// + /// Adds a command callback to a specified command string. + /// + /// The string representing the command i.e "yes" == /yes + /// The method that will be executed on confirmation ie user accepts + public void AddResponse( string name, Action callback) + { + if( AwaitingResponse.ContainsKey(name)) + { + AwaitingResponse.Remove(name); + } - AwaitingResponse.Add(name, callback); - } + AwaitingResponse.Add(name, callback); + } } public class TSRestPlayer : TSPlayer @@ -924,11 +922,6 @@ namespace TShockAPI AwaitingResponse = new Dictionary>(); } - public override void SendMessage(string msg) - { - SendMessage(msg, 0, 255, 0); - } - public override void SendMessage(string msg, Color color) { SendMessage(msg, color.R, color.G, color.B); @@ -967,45 +960,40 @@ namespace TShockAPI public class TSServerPlayer : TSPlayer { - public static string AccountName = "ServerConsole"; + public static string AccountName = "ServerConsole"; public TSServerPlayer() : base("Server") { Group = new SuperAdminGroup(); - UserAccountName = AccountName; + UserAccountName = AccountName; } - public override void SendErrorMessage(string msg) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(msg); - Console.ResetColor(); - } - - public override void SendInfoMessage(string msg) - { - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine(msg); - Console.ResetColor(); - } - - public override void SendSuccessMessage(string msg) - { - Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine(msg); - Console.ResetColor(); - } - - public override void SendWarningMessage(string msg) - { - Console.ForegroundColor = ConsoleColor.DarkRed; - Console.WriteLine(msg); - Console.ResetColor(); - } - - public override void SendMessage(string msg) + public override void SendErrorMessage(string msg) { - SendMessage(msg, 0, 255, 0); + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(msg); + Console.ResetColor(); + } + + public override void SendInfoMessage(string msg) + { + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(msg); + Console.ResetColor(); + } + + public override void SendSuccessMessage(string msg) + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine(msg); + Console.ResetColor(); + } + + public override void SendWarningMessage(string msg) + { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine(msg); + Console.ResetColor(); } public override void SendMessage(string msg, Color color) @@ -1016,7 +1004,6 @@ namespace TShockAPI public override void SendMessage(string msg, byte red, byte green, byte blue) { Console.WriteLine(msg); - //RconHandler.Response += msg + "\n"; } public void SetFullMoon() @@ -1093,7 +1080,7 @@ namespace TShockAPI int spawnTileX; int spawnTileY; TShock.Utils.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX, - out spawnTileY); + out spawnTileY); int npcid = NPC.NewNPC(spawnTileX*16, spawnTileY*16, type, 0); // This is for special slimes Main.npc[npcid].SetDefaults(name); @@ -1407,19 +1394,19 @@ namespace TShockAPI NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[8].name, player.Index, 67f, (float)Main.player[player.Index].armor[8].prefix, 0f, 0); NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[9].name, player.Index, 68f, (float)Main.player[player.Index].armor[9].prefix, 0f, 0); NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[10].name, player.Index, 69f, (float)Main.player[player.Index].armor[10].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[11].name, player.Index, 70f, (float)Main.player[player.Index].armor[11].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[12].name, player.Index, 71f, (float)Main.player[player.Index].armor[12].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[13].name, player.Index, 72f, (float)Main.player[player.Index].armor[13].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[14].name, player.Index, 73f, (float)Main.player[player.Index].armor[14].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[15].name, player.Index, 74f, (float)Main.player[player.Index].armor[15].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[11].name, player.Index, 70f, (float)Main.player[player.Index].armor[11].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[12].name, player.Index, 71f, (float)Main.player[player.Index].armor[12].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[13].name, player.Index, 72f, (float)Main.player[player.Index].armor[13].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[14].name, player.Index, 73f, (float)Main.player[player.Index].armor[14].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].armor[15].name, player.Index, 74f, (float)Main.player[player.Index].armor[15].prefix, 0f, 0); NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[0].name, player.Index, 75f, (float)Main.player[player.Index].dye[0].prefix, 0f, 0); NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[1].name, player.Index, 76f, (float)Main.player[player.Index].dye[1].prefix, 0f, 0); NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[2].name, player.Index, 77f, (float)Main.player[player.Index].dye[2].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[3].name, player.Index, 78f, (float)Main.player[player.Index].dye[3].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[4].name, player.Index, 79f, (float)Main.player[player.Index].dye[4].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[5].name, player.Index, 80f, (float)Main.player[player.Index].dye[5].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[6].name, player.Index, 81f, (float)Main.player[player.Index].dye[6].prefix, 0f, 0); - NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[7].name, player.Index, 82f, (float)Main.player[player.Index].dye[7].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[3].name, player.Index, 78f, (float)Main.player[player.Index].dye[3].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[4].name, player.Index, 79f, (float)Main.player[player.Index].dye[4].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[5].name, player.Index, 80f, (float)Main.player[player.Index].dye[5].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[6].name, player.Index, 81f, (float)Main.player[player.Index].dye[6].prefix, 0f, 0); + NetMessage.SendData(5, -1, -1, Main.player[player.Index].dye[7].name, player.Index, 82f, (float)Main.player[player.Index].dye[7].prefix, 0f, 0); NetMessage.SendData(4, -1, -1, player.Name, player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(42, -1, -1, "", player.Index, 0f, 0f, 0f, 0); NetMessage.SendData(16, -1, -1, "", player.Index, 0f, 0f, 0f, 0); @@ -1428,30 +1415,31 @@ namespace TShockAPI { NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].inventory[k].name, player.Index, (float)k, (float)Main.player[player.Index].inventory[k].prefix, 0f, 0); } - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[0].name, player.Index, 59f, (float)Main.player[player.Index].armor[0].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[1].name, player.Index, 60f, (float)Main.player[player.Index].armor[1].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[2].name, player.Index, 61f, (float)Main.player[player.Index].armor[2].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[3].name, player.Index, 62f, (float)Main.player[player.Index].armor[3].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[4].name, player.Index, 63f, (float)Main.player[player.Index].armor[4].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[5].name, player.Index, 64f, (float)Main.player[player.Index].armor[5].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[6].name, player.Index, 65f, (float)Main.player[player.Index].armor[6].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[7].name, player.Index, 66f, (float)Main.player[player.Index].armor[7].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[8].name, player.Index, 67f, (float)Main.player[player.Index].armor[8].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[9].name, player.Index, 68f, (float)Main.player[player.Index].armor[9].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[10].name, player.Index, 69f, (float)Main.player[player.Index].armor[10].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[11].name, player.Index, 70f, (float)Main.player[player.Index].armor[11].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[12].name, player.Index, 71f, (float)Main.player[player.Index].armor[12].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[13].name, player.Index, 72f, (float)Main.player[player.Index].armor[13].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[14].name, player.Index, 73f, (float)Main.player[player.Index].armor[14].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[15].name, player.Index, 74f, (float)Main.player[player.Index].armor[15].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[0].name, player.Index, 75f, (float)Main.player[player.Index].dye[0].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[1].name, player.Index, 76f, (float)Main.player[player.Index].dye[1].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[2].name, player.Index, 77f, (float)Main.player[player.Index].dye[2].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[3].name, player.Index, 78f, (float)Main.player[player.Index].dye[3].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[4].name, player.Index, 79f, (float)Main.player[player.Index].dye[4].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[5].name, player.Index, 80f, (float)Main.player[player.Index].dye[5].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[6].name, player.Index, 81f, (float)Main.player[player.Index].dye[6].prefix, 0f, 0); - NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[7].name, player.Index, 82f, (float)Main.player[player.Index].dye[7].prefix, 0f, 0); + + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[0].name, player.Index, 59f, (float)Main.player[player.Index].armor[0].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[1].name, player.Index, 60f, (float)Main.player[player.Index].armor[1].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[2].name, player.Index, 61f, (float)Main.player[player.Index].armor[2].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[3].name, player.Index, 62f, (float)Main.player[player.Index].armor[3].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[4].name, player.Index, 63f, (float)Main.player[player.Index].armor[4].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[5].name, player.Index, 64f, (float)Main.player[player.Index].armor[5].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[6].name, player.Index, 65f, (float)Main.player[player.Index].armor[6].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[7].name, player.Index, 66f, (float)Main.player[player.Index].armor[7].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[8].name, player.Index, 67f, (float)Main.player[player.Index].armor[8].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[9].name, player.Index, 68f, (float)Main.player[player.Index].armor[9].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[10].name, player.Index, 69f, (float)Main.player[player.Index].armor[10].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[11].name, player.Index, 70f, (float)Main.player[player.Index].armor[11].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[12].name, player.Index, 71f, (float)Main.player[player.Index].armor[12].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[13].name, player.Index, 72f, (float)Main.player[player.Index].armor[13].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[14].name, player.Index, 73f, (float)Main.player[player.Index].armor[14].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].armor[15].name, player.Index, 74f, (float)Main.player[player.Index].armor[15].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[0].name, player.Index, 75f, (float)Main.player[player.Index].dye[0].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[1].name, player.Index, 76f, (float)Main.player[player.Index].dye[1].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[2].name, player.Index, 77f, (float)Main.player[player.Index].dye[2].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[3].name, player.Index, 78f, (float)Main.player[player.Index].dye[3].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[4].name, player.Index, 79f, (float)Main.player[player.Index].dye[4].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[5].name, player.Index, 80f, (float)Main.player[player.Index].dye[5].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[6].name, player.Index, 81f, (float)Main.player[player.Index].dye[6].prefix, 0f, 0); + NetMessage.SendData(5, player.Index, -1, Main.player[player.Index].dye[7].name, player.Index, 82f, (float)Main.player[player.Index].dye[7].prefix, 0f, 0); 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); NetMessage.SendData(16, player.Index, -1, "", player.Index, 0f, 0f, 0f, 0); diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 04a4551f..1c8177a7 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -36,29 +36,27 @@ using Terraria; using TerrariaApi.Server; using TShockAPI.DB; using TShockAPI.Net; -using System.Threading; -using System.Threading.Tasks; using TShockAPI.ServerSideCharacters; namespace TShockAPI { - [ApiVersion(1, 16)] + [ApiVersion(1, 17)] public class TShock : TerrariaPlugin { public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version; - public static readonly string VersionCodename = "And the great beast rose from its slumber, ready to take on the world again."; + public static readonly string VersionCodename = "2015!!"; public static string SavePath = "tshock"; private const string LogFormatDefault = "yyyy-MM-dd_HH-mm-ss"; private static string LogFormat = LogFormatDefault; private const string LogPathDefault = "tshock"; private static string LogPath = LogPathDefault; - private static bool LogClear = false; + private static bool LogClear; public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers]; public static BanManager Bans; public static WarpManager Warps; - public static RegionManager Regions; + public static RegionManager Regions; public static BackupManager Backups; public static GroupManager Groups; public static UserManager Users; @@ -76,7 +74,9 @@ namespace TShockAPI public static SecureRest RestApi; public static RestManager RestManager; public static Utils Utils = Utils.Instance; + public static StatTracker StatTracker = new StatTracker(); public static UpdateManager UpdateManager; + public static ILog Log; /// /// Used for implementing REST Tokens prior to the REST system starting up. /// @@ -107,10 +107,6 @@ namespace TShockAPI get { return "The administration modification of the future."; } } - public override string UpdateURL - { - get { return ""; } - } public TShock(Main game) : base(game) { @@ -126,13 +122,13 @@ namespace TShockAPI [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] public override void Initialize() { + string logFilename; + string logPathSetupWarning; + try { HandleCommandLine(Environment.GetCommandLineArgs()); - if (Version.Major >= 4) - getTShockAscii(); - if (!Directory.Exists(SavePath)) Directory.CreateDirectory(SavePath); @@ -142,37 +138,29 @@ namespace TShockAPI Main.ServerSideCharacter = ServerSideCharacterConfig.Enabled; DateTime now = DateTime.Now; - string logFilename; - string logPathSetupWarning = null; // Log path was not already set by the command line parameter? if (LogPath == LogPathDefault) LogPath = Config.LogPath; try { - logFilename = Path.Combine(LogPath, now.ToString(LogFormat)+".log"); + logFilename = Path.Combine(LogPath, now.ToString(LogFormat) + ".log"); if (!Directory.Exists(LogPath)) Directory.CreateDirectory(LogPath); } - catch(Exception ex) + catch (Exception ex) { - logPathSetupWarning = "Could not apply the given log path / log format, defaults will be used. Exception details:\n" + ex; - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(logPathSetupWarning); - Console.ForegroundColor = ConsoleColor.Gray; + logPathSetupWarning = + "Could not apply the given log path / log format, defaults will be used. Exception details:\n" + ex; + + ServerApi.LogWriter.PluginWriteLine(this, logPathSetupWarning, TraceLevel.Error); + // Problem with the log path or format use the default logFilename = Path.Combine(LogPathDefault, now.ToString(LogFormatDefault) + ".log"); } -#if DEBUG - Log.Initialize(logFilename, LogLevel.All, false); -#else - Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear); -#endif - if (logPathSetupWarning != null) - Log.Warn(logPathSetupWarning); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; } - catch(Exception ex) + catch (Exception ex) { // Will be handled by the server api and written to its crashlog.txt. throw new Exception("Fatal TShock initialization exception. See inner exception for details.", ex); @@ -181,16 +169,6 @@ namespace TShockAPI // Further exceptions are written to TShock's log from now on. try { - if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) - { - Log.ConsoleInfo( - "TShock was improperly shut down. Please use the exit command in the future to prevent this."); - File.Delete(Path.Combine(SavePath, "tshock.pid")); - } - File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture)); - - HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs()); - if (Config.StorageType.ToLower() == "sqlite") { string sql = Path.Combine(SavePath, "tshock.sqlite"); @@ -204,16 +182,16 @@ namespace TShockAPI DB = new MySqlConnection(); DB.ConnectionString = String.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};", - hostport[0], - hostport.Length > 1 ? hostport[1] : "3306", - Config.MySqlDbName, - Config.MySqlUsername, - Config.MySqlPassword + hostport[0], + hostport.Length > 1 ? hostport[1] : "3306", + Config.MySqlDbName, + Config.MySqlUsername, + Config.MySqlPassword ); } catch (MySqlException ex) { - Log.Error(ex.ToString()); + ServerApi.LogWriter.PluginWriteLine(this, ex.ToString(), TraceLevel.Error); throw new Exception("MySql not setup correctly"); } } @@ -222,12 +200,33 @@ namespace TShockAPI throw new Exception("Invalid storage type"); } +#if DEBUG + var level = LogLevel.All; +#else + var level = LogLevel.All & ~LogLevel.Debug; +#endif + if (Config.UseSqlLogs) + Log = new SqlLog(level, DB, logFilename, LogClear); + else + Log = new TextLog(logFilename, level, LogClear); + + if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) + { + Log.ConsoleInfo( + "TShock was improperly shut down. Please use the exit command in the future to prevent this."); + File.Delete(Path.Combine(SavePath, "tshock.pid")); + } + File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), + Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture)); + + HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs()); + Backups = new BackupManager(Path.Combine(SavePath, "backups")); Backups.KeepFor = Config.BackupKeepFor; Backups.Interval = Config.BackupInterval; Bans = new BanManager(DB); Warps = new WarpManager(DB); - Regions = new RegionManager(DB); + Regions = new RegionManager(DB); Users = new UserManager(DB); Groups = new GroupManager(DB); Itembans = new ItemManager(DB); @@ -244,7 +243,7 @@ namespace TShockAPI if (Config.EnableGeoIP && File.Exists(geoippath)) Geo = new GeoIPCountry(geoippath); - Log.ConsoleInfo(string.Format("|> Version {0} ({1}) now running.", Version, VersionCodename)); + Log.ConsoleInfo("TShock {0} ({1}) now running.", Version, VersionCodename); ServerApi.Hooks.GamePostInitialize.Register(this, OnPostInit); ServerApi.Hooks.GameUpdate.Register(this, OnUpdate); @@ -262,15 +261,16 @@ namespace TShockAPI ServerApi.Hooks.ProjectileSetDefaults.Register(this, OnProjectileSetDefaults); ServerApi.Hooks.WorldStartHardMode.Register(this, OnStartHardMode); ServerApi.Hooks.WorldSave.Register(this, SaveManager.Instance.OnSaveWorld); - ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck); + ServerApi.Hooks.WorldChristmasCheck.Register(this, OnXmasCheck); ServerApi.Hooks.WorldHalloweenCheck.Register(this, OnHalloweenCheck); ServerApi.Hooks.NetNameCollision.Register(this, NetHooks_NameCollision); - TShockAPI.Hooks.PlayerHooks.PlayerPreLogin += OnPlayerPreLogin; - TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin; + Hooks.PlayerHooks.PlayerPreLogin += OnPlayerPreLogin; + Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin; + Hooks.AccountHooks.AccountDelete += OnAccountDelete; + Hooks.AccountHooks.AccountCreate += OnAccountCreate; GetDataHandlers.InitGetDataHandler(); Commands.InitCommands(); - //RconHandler.StartThread(); if (Config.RestApiEnabled) RestApi.Start(); @@ -283,6 +283,8 @@ namespace TShockAPI if (Initialized != null) Initialized(); + + Log.ConsoleInfo("Welcome to TShock for Terraria. Initialization complete."); } catch (Exception ex) { @@ -292,25 +294,6 @@ namespace TShockAPI } } - private static void getTShockAscii() - { -// ReSharper disable LocalizableElement - Console.Write(" ___ ___ ___ ___ ___ \n" + - " ___ / /\\ /__/\\ / /\\ / /\\ /__/| \n" + - " / /\\ / /:/_ \\ \\:\\ / /::\\ / /:/ | |:| \n" + - " / /:/ / /:/ /\\ \\__\\:\\ / /:/\\:\\ / /:/ | |:| \n" + - " / /:/ / /:/ /::\\ ___ / /::\\ / /:/ \\:\\ / /:/ ___ __| |:| \n" + - " / /::\\ /__/:/ /:/\\:\\/__/\\ /:/\\:\\/__/:/ \\__\\:\\/__/:/ / /\\/__/\\_|:|____\n" + - "/__/:/\\:\\\\ \\:\\/:/~/:/\\ \\:\\/:/__\\/\\ \\:\\ / /:/\\ \\:\\ / /:/\\ \\:\\/:::::/\n" + - "\\__\\/ \\:\\\\ \\::/ /:/ \\ \\::/ \\ \\:\\ /:/ \\ \\:\\ /:/ \\ \\::/~~~~ \n" + - " \\ \\:\\\\__\\/ /:/ \\ \\:\\ \\ \\:\\/:/ \\ \\:\\/:/ \\ \\:\\ \n" + - " \\__\\/ /__/:/ \\ \\:\\ \\ \\::/ \\ \\::/ \\ \\:\\ \n" + - " \\__\\/ \\__\\/ \\__\\/ \\__\\/ \\__\\/ \n" + - ""); - Console.WriteLine("TShock for Terraria is open & free software. If you paid, you were scammed."); -// ReSharper restore LocalizableElement - } - protected override void Dispose(bool disposing) { if (disposing) @@ -342,7 +325,7 @@ namespace TShockAPI ServerApi.Hooks.WorldChristmasCheck.Deregister(this, OnXmasCheck); ServerApi.Hooks.WorldHalloweenCheck.Deregister(this, OnHalloweenCheck); ServerApi.Hooks.NetNameCollision.Deregister(this, NetHooks_NameCollision); - TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin; + TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin; if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) { @@ -379,6 +362,16 @@ namespace TShockAPI Users.UpdateLogin(u); } + private void OnAccountDelete(Hooks.AccountDeleteEventArgs args) + { + CharacterDB.RemovePlayer(args.User.ID); + } + + private void OnAccountCreate(Hooks.AccountCreateEventArgs args) + { + CharacterDB.SeedInitialData(Users.GetUser(args.User)); + } + private void OnPlayerPreLogin(Hooks.PlayerPreLoginEventArgs args) { if (args.Player.IsLoggedIn) @@ -418,17 +411,17 @@ namespace TShockAPI } } - private void OnXmasCheck(ChristmasCheckEventArgs args) - { - if (args.Handled) - return; + private void OnXmasCheck(ChristmasCheckEventArgs args) + { + if (args.Handled) + return; - if(Config.ForceXmas) - { - args.Xmas = true; - args.Handled = true; - } + if(Config.ForceXmas) + { + args.Xmas = true; + args.Handled = true; } + } private void OnHalloweenCheck(HalloweenCheckEventArgs args) { @@ -572,14 +565,14 @@ namespace TShockAPI private void OnPostInit(EventArgs args) { - SetConsoleTitle(); + SetConsoleTitle(false); if (!File.Exists(Path.Combine(SavePath, "auth.lck")) && !File.Exists(Path.Combine(SavePath, "authcode.txt"))) { var r = new Random((int) DateTime.Now.ToBinary()); AuthToken = r.Next(100000, 10000000); Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine("TShock Notice: To become SuperAdmin, join the game and type /auth " + AuthToken); - Console.WriteLine("This token will display until disabled by verification. (/auth-verify)"); + Console.WriteLine("TShock Notice: To become SuperAdmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); + Console.WriteLine("This token will display until disabled by verification. ({0}auth-verify)", Commands.Specifier); Console.ForegroundColor = ConsoleColor.Gray; FileTools.CreateFile(Path.Combine(SavePath, "authcode.txt")); using (var tw = new StreamWriter(Path.Combine(SavePath, "authcode.txt"))) @@ -596,8 +589,8 @@ namespace TShockAPI Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine( "TShock Notice: authcode.txt is still present, and the AuthToken located in that file will be used."); - Console.WriteLine("To become superadmin, join the game and type /auth " + AuthToken); - Console.WriteLine("This token will display until disabled by verification. (/auth-verify)"); + Console.WriteLine("To become superadmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); + Console.WriteLine("This token will display until disabled by verification. ({0}auth-verify)", Commands.Specifier); Console.ForegroundColor = ConsoleColor.Gray; } else @@ -613,6 +606,7 @@ namespace TShockAPI FixChestStacks(); UpdateManager = new UpdateManager(); + StatTracker.Initialize(); } private void ComputeMaxStyles() @@ -811,7 +805,7 @@ namespace TShockAPI player.SetBuff(36, 120); //Broken Armor check = "Remove armor/accessory " + item.name; - player.SendErrorMessage(string.Format("You are wearing banned equipment. {0}", check)); + player.SendErrorMessage("You are wearing banned equipment. {0}", check); break; } } @@ -824,16 +818,32 @@ namespace TShockAPI { player.SetBuff(23, 120); //Cursed } + + var oldRegion = player.CurrentRegion; + player.CurrentRegion = Regions.GetTopRegion(Regions.InAreaRegion(player.TileX, player.TileY)); + + if (oldRegion != player.CurrentRegion) + { + if (oldRegion != null) + { + Hooks.RegionHooks.OnRegionLeft(player, oldRegion); + } + + if (player.CurrentRegion != null) + { + Hooks.RegionHooks.OnRegionEntered(player); + } + } } } - SetConsoleTitle(); + SetConsoleTitle(false); } - private void SetConsoleTitle() + private void SetConsoleTitle(bool empty) { - Console.Title = string.Format("{0}{1}/{2} @ {3}:{4} (TerrariaShock v{5})", + Console.Title = string.Format("{0}{1}/{2} @ {3}:{4} (TShock for Terraria v{5})", !string.IsNullOrWhiteSpace(Config.ServerName) ? Config.ServerName + " - " : "", - Utils.ActivePlayers(), + empty ? 0 : Utils.ActivePlayers(), Config.MaxSlots, Netplay.serverListenIP, Netplay.serverPort, Version); } @@ -997,7 +1007,7 @@ namespace TShockAPI { if (!tsplr.SilentKickInProgress && tsplr.State >= 3) Utils.Broadcast(tsplr.Name + " has left.", Color.Yellow); - Log.Info(string.Format("{0} disconnected.", tsplr.Name)); + Log.Info("{0} disconnected.", tsplr.Name); if (tsplr.IsLoggedIn && !tsplr.IgnoreActionsForClearingTrashCan && Main.ServerSideCharacter && (!tsplr.Dead || tsplr.TPlayer.difficulty != 2)) { @@ -1010,6 +1020,14 @@ namespace TShockAPI RememberedPos.InsertLeavePos(tsplr.Name, tsplr.IP, (int) (tsplr.X/16), (int) (tsplr.Y/16)); } } + + // The last player will leave after this hook is executed. + if (Utils.ActivePlayers() == 1) + { + if (Config.SaveWorldOnLastPlayerExit) + SaveManager.Instance.SaveWorld(); + SetConsoleTitle(true); + } } private void OnChat(ServerChatEventArgs args) @@ -1037,7 +1055,8 @@ namespace TShockAPI return; }*/ - if (args.Text.StartsWith(Config.CommandSpecifier) && !string.IsNullOrWhiteSpace(args.Text.Substring(1))) + if ((args.Text.StartsWith(Config.CommandSpecifier) || args.Text.StartsWith(Config.CommandSilentSpecifier)) + && !string.IsNullOrWhiteSpace(args.Text.Substring(1))) { try { @@ -1045,7 +1064,7 @@ namespace TShockAPI } catch (Exception ex) { - Log.ConsoleError("Command exception"); + Log.ConsoleError("An exeption occurred executing a command."); Log.Error(ex.ToString()); } } @@ -1087,7 +1106,7 @@ namespace TShockAPI tsplr.SendMessage(msg, tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); TSPlayer.Server.SendMessage(msg, tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); - Log.Info(string.Format("Broadcast: {0}", msg)); + Log.Info("Broadcast: {0}", msg); args.Handled = true; } } @@ -1113,7 +1132,7 @@ namespace TShockAPI WorldGen.genRand = new Random(); } - if (args.Command.StartsWith("playing") || args.Command.StartsWith("/playing")) + if (args.Command.StartsWith("playing") || args.Command.StartsWith("{0}playing".SFormat(Commands.Specifier))) { int count = 0; foreach (TSPlayer player in Players) @@ -1121,18 +1140,18 @@ namespace TShockAPI if (player != null && player.Active) { count++; - TSPlayer.Server.SendInfoMessage(string.Format("{0} ({1}) [{2}] <{3}>", player.Name, player.IP, - player.Group.Name, player.UserAccountName)); + TSPlayer.Server.SendInfoMessage("{0} ({1}) [{2}] <{3}>", player.Name, player.IP, + player.Group.Name, player.UserAccountName); } } - TSPlayer.Server.SendInfoMessage(string.Format("{0} players connected.", count)); + TSPlayer.Server.SendInfoMessage("{0} players connected.", count); } else if (args.Command == "autosave") { Main.autoSave = Config.AutoSave = !Config.AutoSave; Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled")); } - else if (args.Command.StartsWith("/")) + else if (args.Command.StartsWith(Commands.Specifier)) { Commands.HandleCommand(TSPlayer.Server, args.Command); } @@ -1190,24 +1209,24 @@ namespace TShockAPI player.LoginMS = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - if (TShock.Config.EnableGeoIP && TShock.Geo != null) + if (Config.EnableGeoIP && TShock.Geo != null) { - Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP, + Log.Info("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP, player.Group.Name, player.Country, TShock.Utils.ActivePlayers(), - TShock.Config.MaxSlots)); + TShock.Config.MaxSlots); if (!player.SilentJoinInProgress) - TShock.Utils.Broadcast(string.Format("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow); + Utils.Broadcast(string.Format("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow); } else { - Log.Info(string.Format("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP, - player.Group.Name, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots)); + Log.Info("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP, + player.Group.Name, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots); if (!player.SilentJoinInProgress) - TShock.Utils.Broadcast(player.Name + " has joined.", Color.Yellow); + Utils.Broadcast(player.Name + " has joined.", Color.Yellow); } - if (TShock.Config.DisplayIPToAdmins) - TShock.Utils.SendLogs(string.Format("{0} has joined. IP: {1}", player.Name, player.IP), Color.Blue); + if (Config.DisplayIPToAdmins) + Utils.SendLogs(string.Format("{0} has joined. IP: {1}", player.Name, player.IP), Color.Blue); Utils.ShowFileToUser(player, "motd.txt"); @@ -1223,14 +1242,13 @@ namespace TShockAPI { if (Main.ServerSideCharacter) { - player.SendMessage( - player.IgnoreActionsForInventory = "Server side characters is enabled! Please /register or /login to play!", - Color.Red); + player.SendErrorMessage( + player.IgnoreActionsForInventory = "Server side characters is enabled! Please {0}register or {0}login to play!", Commands.Specifier); player.LoginHarassed = true; } else if (Config.RequireLogin) { - player.SendMessage("Please /register or /login to play!", Color.Red); + player.SendErrorMessage("Please {0}register or {0}login to play!", Commands.Specifier); player.LoginHarassed = true; } } @@ -1240,7 +1258,7 @@ namespace TShockAPI if (Config.RememberLeavePos && (RememberedPos.GetLeavePos(player.Name, player.IP) != Vector2.Zero) && !player.LoginHarassed) { player.RPPending = 3; - player.SendMessage("You will be teleported to your last known location...", Color.Red); + player.SendInfoMessage("You will be teleported to your last known location..."); } args.Handled = true; @@ -1552,7 +1570,7 @@ namespace TShockAPI if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) { - player.SendMessage("You do not have permission to build!", Color.Red); + player.SendErrorMessage("You do not have permission to build!"); player.BPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1566,7 +1584,7 @@ namespace TShockAPI if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) { - player.SendMessage("You do not have permission to build!", Color.Red); + player.SendErrorMessage("You do not have permission to build!"); player.BPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1577,7 +1595,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000) { - player.SendMessage("This region is protected from changes.", Color.Red); + player.SendErrorMessage("This region is protected from changes."); player.RPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1589,7 +1607,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) { - player.SendMessage("The world is protected from changes.", Color.Red); + player.SendErrorMessage("The world is protected from changes."); player.WPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1604,7 +1622,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 2000) { - player.SendMessage("Spawn is protected from changes.", Color.Red); + player.SendErrorMessage("Spawn is protected from changes."); player.SPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1621,7 +1639,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000) { - player.SendMessage("You do not have permission to build!", Color.Red); + player.SendErrorMessage("You do not have permission to build!"); player.BPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1632,7 +1650,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000) { - player.SendMessage("This region is protected from changes.", Color.Red); + player.SendErrorMessage("This region is protected from changes."); player.RPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1644,7 +1662,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000) { - player.SendMessage("The world is protected from changes.", Color.Red); + player.SendErrorMessage("The world is protected from changes."); player.WPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1659,7 +1677,7 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 1000) { - player.SendMessage("Spawn is protected from changes.", Color.Red); + player.SendErrorMessage("Spawn is protected from changes."); player.SPm = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; } return true; @@ -1778,9 +1796,6 @@ namespace TShockAPI Netplay.password = ""; Netplay.spamCheck = false; - RconHandler.Password = file.RconPassword; - RconHandler.ListenPort = file.RconPort; - Utils.HashAlgo = file.HashAlgorithm; } } diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 4072b8ed..176e11dd 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -39,6 +39,7 @@ true bin\Debug\TShockAPI.XML x86 + 1591 pdbonly @@ -78,6 +79,11 @@ + + + + + @@ -102,7 +108,6 @@ - @@ -111,7 +116,6 @@ - True @@ -182,7 +186,7 @@ - +