diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 5a81c44b..71594c46 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -160,6 +160,7 @@ namespace TShockAPI add(Permissions.managegroup, AddGroup, "addgroup"); add(Permissions.managegroup, DeleteGroup, "delgroup"); add(Permissions.managegroup, ModifyGroup, "modgroup"); + add(Permissions.managegroup, ViewGroups, "group"); add(Permissions.manageitem, AddItem, "additem", "banitem"); add(Permissions.manageitem, DeleteItem, "delitem", "unbanitem"); add(Permissions.manageitem, ListItems, "listitems", "listbanneditems"); @@ -209,6 +210,7 @@ namespace TShockAPI add(Permissions.hardmode, StartHardMode, "hardmode"); add(Permissions.hardmode, DisableHardMode, "stophardmode", "disablehardmode"); add(Permissions.cfg, ServerInfo, "stats"); + add(Permissions.cfg, WorldInfo, "world"); add(Permissions.converthardmode, ConvertCorruption, "convertcorruption"); add(Permissions.converthardmode, ConvertHallow, "converthallow"); } @@ -678,6 +680,12 @@ namespace TShockAPI args.Player.SendMessage("Machine name: " + Environment.MachineName); } + public static void WorldInfo(CommandArgs args) + { + args.Player.SendMessage("World Name: " + Main.worldName); + args.Player.SendMessage("World ID: " + Main.worldID); + } + #endregion #region Player Management Commands @@ -693,12 +701,24 @@ namespace TShockAPI var players = TShock.Utils.FindPlayer(args.Parameters[0]); if (players.Count > 1) { - args.Player.SendMessage("More than one player matched your query.", Color.Red); + var plrMatches = ""; + foreach (TSPlayer plr in players) + { + if (plrMatches.Length != 0) + { + plrMatches += ", " + plr.Name; + } + else + { + plrMatches += plr.Name; + } + } + args.Player.SendMessage("More than one player matched! Matches: " + plrMatches, Color.Red); return; } try { - args.Player.SendMessage("IP Address: " + players[0].IP + " Logged In As: " + players[0].UserAccountName, Color.Green); + args.Player.SendMessage("IP Address: " + players[0].IP + " Logged In As: " + players[0].UserAccountName + "Group: " + players[0].Group.Name, Color.Green); } catch (Exception) { @@ -727,8 +747,20 @@ namespace TShockAPI } else if (players.Count > 1) { - args.Player.SendMessage("More than one player matched!", Color.Red); - } + var plrMatches = ""; + foreach (TSPlayer plr in players) + { + if (plrMatches.Length != 0) + { + plrMatches += ", " + plr.Name; + } + else + { + plrMatches += plr.Name; + } + } + args.Player.SendMessage("More than one player matched! Matches: " + plrMatches, Color.Red); + } else { string reason = args.Parameters.Count > 1 @@ -762,8 +794,20 @@ namespace TShockAPI } else if (players.Count > 1) { - args.Player.SendMessage("More than one player matched!", Color.Red); - } + var plrMatches = ""; + foreach (TSPlayer plr in players) + { + if (plrMatches.Length != 0) + { + plrMatches += ", " + plr.Name; + } + else + { + plrMatches += plr.Name; + } + } + args.Player.SendMessage("More than one player matched! Matches: " + plrMatches, Color.Red); + } else { string reason = args.Parameters.Count > 1 @@ -1771,6 +1815,80 @@ namespace TShockAPI args.Player.SendMessage("Incorrect format: /modGroup add|del ", Color.Red); } + private static void ViewGroups(CommandArgs args) + { + if (args.Parameters.Count > 0) + { + String com = args.Parameters[0]; + + if( com == "list" ) + { + string ret = "Groups: "; + foreach( Group g in TShock.Groups.groups ) + { + if (ret.Length > 50) + { + args.Player.SendMessage(ret, Color.Green); + ret = ""; + } + + if( ret != "" ) + { + ret += ", "; + } + + ret += g.Name; + } + + if (ret.Length > 0) + { + args.Player.SendMessage(ret, Color.Green); + } + return; + } + else if( com == "perm") + { + if (args.Parameters.Count > 1) + { + String groupname = args.Parameters[1]; + + if( TShock.Groups.GroupExists( groupname ) ) + { + string ret = String.Format("Permissions for {0}: ", groupname); + foreach (string p in TShock.Utils.GetGroup( groupname ).permissions) + { + if (ret.Length > 50) + { + args.Player.SendMessage(ret, Color.Green); + ret = ""; + } + + if (ret != "") + { + ret += ", "; + } + + ret += p; + } + if (ret.Length > 0) + { + args.Player.SendMessage(ret, Color.Green); + } + + return; + } + else + { + args.Player.SendMessage("Group does not exist.", Color.Red); + return; + } + } + } + } + args.Player.SendMessage("Incorrect format: /group list", Color.Red); + args.Player.SendMessage(" /group perm ", Color.Red); + } + #endregion Group Management #region Item Management @@ -2600,7 +2718,10 @@ namespace TShockAPI private static void Playing(CommandArgs args) { - args.Player.SendMessage(string.Format("Current players: {0}.", TShock.Utils.GetPlayers()), 255, 240, 20); + string response = args.Player.Group.HasPermission(Permissions.seeids) + ? TShock.Utils.GetPlayersWithIds() + : TShock.Utils.GetPlayers(); + args.Player.SendMessage(string.Format("Current players: {0}.", response), 255, 240, 20); args.Player.SendMessage(string.Format("TShock: {0} ({1}): ({2}/{3})", TShock.VersionNum, TShock.VersionCodename, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots)); } diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs index 5257e258..f1caa8f8 100644 --- a/TShockAPI/ConfigFile.cs +++ b/TShockAPI/ConfigFile.cs @@ -151,6 +151,8 @@ namespace TShockAPI [Description("Enable Server Side Inventory checks, EXPERIMENTAL")] public bool ServerSideInventory; + [Description("Time, in milliseconds, to disallow discarding items after logging in when ServerSideInventory is ON")] public int LogonDiscardThreshold=250; + [Description("Disables reporting of playercount to the stat system.")] public bool DisablePlayerCountReporting; [Description("Disables clown bomb projectiles from spawning")] public bool DisableClownBombs; @@ -175,6 +177,9 @@ namespace TShockAPI [Description("Disable a player if they exceed this number of projectile new within 1 second.")] public int ProjectileThreshold = 50; + [Description("Ignore shrapnel from crystal bullets for Projectile Threshold.")] public bool + ProjIgnoreShrapnel = true; + [Description("Require all players to register or login before being allowed to play.")] public bool RequireLogin; [Description( @@ -200,7 +205,7 @@ namespace TShockAPI [Description("The maximum damage a projectile can inflict")] public int MaxProjDamage = 175; [Description("Ignores checking to see if player 'can' update a projectile")] public bool IgnoreProjUpdate = false; - + [Description("Ignores checking to see if player 'can' kill a projectile")] public bool IgnoreProjKill = false; [Description("Ignores all no clip checks for players")] public bool IgnoreNoClip = false; diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index eb16c225..9935c96c 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -1426,7 +1426,7 @@ namespace TShockAPI { continue; }*/ - if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105)) + if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105) || (tile.type == 139 && newtile.Type == 139)) { if (TShock.Config.EnableInsecureTileFixes) { @@ -1896,7 +1896,7 @@ namespace TShockAPI // Server now checks owner + ident, if owner is different, server will create new projectile. /*if (args.Player.Index != owner) { - args.Player.Disable("Owner and player ID does not match to update projectile"); + 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; }*/ @@ -1916,8 +1916,15 @@ namespace TShockAPI if (!TShock.Config.IgnoreProjUpdate && TShock.CheckProjectilePermission(args.Player, index, type)) { - args.Player.Disable("Does not have projectile permission to update projectile."); - args.Player.RemoveProjectile(ident, owner); + if (type == 100) + { //fix for skele prime + Log.Debug("Skeletron Prime's death laser ignored for cheat detection.."); + } + else + { + args.Player.Disable("Does not have projectile permission to update projectile."); + args.Player.RemoveProjectile(ident, owner); + } return true; } @@ -1936,7 +1943,14 @@ namespace TShockAPI if (!args.Player.Group.HasPermission(Permissions.ignoreprojectiledetection)) { - args.Player.ProjectileThreshold++; + if ((type ==90) && (TShock.Config.ProjIgnoreShrapnel))// ignore shrapnel + { + Log.Debug("Ignoring shrapnel per config.."); + } + else + { + args.Player.ProjectileThreshold++; + } } return false; @@ -1959,7 +1973,7 @@ namespace TShockAPI // 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("Owner and player ID does not match to kill projectile"); + 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)); args.Player.RemoveProjectile(ident, owner); return true; }*/ @@ -2360,7 +2374,14 @@ namespace TShockAPI args.Player.SendData(PacketTypes.ItemDrop, "", id); return true; } - + if ((TShock.Config.ServerSideInventory) && (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond - args.Player.LoginMS < TShock.Config.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)); + args.Player.SendData(PacketTypes.ItemDrop, "", id); + return true; + + } if (TShock.CheckIgnores(args.Player)) { args.Player.SendData(PacketTypes.ItemDrop, "", id); @@ -2591,7 +2612,47 @@ namespace TShockAPI return true; if (plr != args.Player.Index) return true; + + string boss; + switch (Type) + { + case -2: + boss = "the Snow Legion"; + break; + case -1: + boss = "a Goblin Invasion"; + break; + case 4: + boss = "the Eye of Cthulhu"; + break; + case 13: + boss = "the Eater of Worlds"; + break; + case 50: + boss = "the King Slime"; + break; + case 125: + boss = "Retinazer"; + break; + case 126: + boss = "Spazmatism"; + break; + case 134: + boss = "the Destroyer"; + break; + case sbyte.MaxValue: + boss = "Skeleton Prime"; + break; + case 128: + boss = "Skeleton Prime"; + break; + default: + boss = "error"; + break; + } + + TShock.Utils.SendLogs(string.Format("{0} summoned {1}", args.Player.Name, boss), Color.Red); return false; } } -} \ No newline at end of file +} diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index 97d6e7e4..fb79bdca 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -158,7 +158,10 @@ namespace TShockAPI [Description("User can start invasions (Goblin/Snow Legion) using items")] public static readonly string startinvasion; - static Permissions() + [Description("User can see the id of players with /who")] + public static readonly string seeids; + + static Permissions() { foreach (var field in typeof (Permissions).GetFields()) { diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index 662dad56..5beaf1ff 100644 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -48,5 +48,5 @@ using System.Runtime.InteropServices; // Build Number // MMdd of the build -[assembly: AssemblyVersion("3.5.1.0122")] -[assembly: AssemblyFileVersion("3.5.1.0122")] +[assembly: AssemblyVersion("3.5.2.0127")] +[assembly: AssemblyFileVersion("3.5.2.0127")] diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 04b34805..ce1f3261 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -76,11 +76,11 @@ namespace TShockAPI public bool RequiresPassword; public bool SilentKickInProgress; public List IceTiles; - public long RPm=1; - public long WPm=1; - public long SPm=1; - public long BPm=1; - + public long RPm=1; + public long WPm=1; + public long SPm=1; + public long BPm=1; + public long LoginMS; public bool RealPlayer { @@ -268,8 +268,8 @@ namespace TShockAPI SendWorldInfo(Main.spawnTileX, Main.spawnTileY, false); - TPlayer.position.X = tilex * 16; - TPlayer.position.Y = tiley * 16; + TPlayer.position.X = (float)(tilex * 16 + 8 - TPlayer.width /2); + TPlayer.position.Y = (float)(tiley * 16 - TPlayer.height); return true; } @@ -308,22 +308,26 @@ namespace TShockAPI } } - public virtual bool SendTileSquare(int x, int y, int size = 10) - { - try - { - int num = (size - 1)/2; - SendData(PacketTypes.TileSendSquare, "", size, (x - num), (y - num)); - return true; - } - catch (Exception ex) - { - Log.Error(ex.ToString()); - } - return false; - } + public virtual bool SendTileSquare(int x, int y, int size = 10) + { + try + { + int num = (size - 1)/2; + SendData(PacketTypes.TileSendSquare, "", size, (x - num), (y - num)); + return true; + } + catch (IndexOutOfRangeException) + { + // This is expected if square exceeds array. + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + return false; + } - 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); // This is for special pickaxe/hammers/swords etc diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index b4531662..abd70cb1 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -41,7 +41,7 @@ namespace TShockAPI public class TShock : TerrariaPlugin { public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version; - public static readonly string VersionCodename = "1.1.2 in the house!"; + public static readonly string VersionCodename = "Squashing bugs, and adding suggestions"; public static string SavePath = "tshock"; @@ -819,7 +819,8 @@ namespace TShockAPI e.Handled = true; return; } - + player.LoginMS= DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + Utils.ShowFileToUser(player, "motd.txt"); if (Config.PvPMode == "always" && !player.TPlayer.hostile) @@ -1153,10 +1154,9 @@ namespace TShockAPI { if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 2000){ player.SendMessage("Spawn protected from changes.", Color.Red); - player.SPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - -} - return true; + player.SPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + } + return true; } } } @@ -1167,14 +1167,14 @@ namespace TShockAPI { if (!player.Group.HasPermission(Permissions.canbuild)) { + if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.BPm) > 2000){ player.SendMessage("You do not have permission to build!", Color.Red); - player.BPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - -} - + player.BPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + } return true; } + if (!player.Group.HasPermission(Permissions.editspawn) && !Regions.CanBuild(tileX, tileY, player) && Regions.InArea(tileX, tileY)) { @@ -1182,24 +1182,19 @@ namespace TShockAPI if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.RPm) > 2000){ player.SendMessage("Region protected from changes.", Color.Red); - player.RPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - -} - - + player.RPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + } return true; } + if (Config.DisableBuild) { if (!player.Group.HasPermission(Permissions.editspawn)) { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000){ + if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.WPm) > 2000){ player.SendMessage("World protected from changes.", Color.Red); - player.WPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - -} - - + player.WPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + } return true; } } @@ -1210,11 +1205,11 @@ namespace TShockAPI var flag = CheckSpawn(tileX, tileY); if (flag) { - if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 1000){ + if (((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - player.SPm) > 1000){ player.SendMessage("Spawn protected from changes.", Color.Red); - player.SPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; + player.SPm=DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; -} + } return true; diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 05579b95..d5c723b9 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -69,6 +69,29 @@ namespace TShockAPI return sb.ToString(); } + /// + /// Used for some places where a list of players might be used. + /// + /// String of players and their id seperated by commas. + public string GetPlayersWithIds() + { + var sb = new StringBuilder(); + foreach (TSPlayer player in TShock.Players) + { + if (player != null && player.Active) + { + if (sb.Length != 0) + { + sb.Append(", "); + } + sb.Append(player.Name); + string id = "( " + Convert.ToString(TShock.Users.GetUserID(player.UserAccountName)) + " )"; + sb.Append(id); + } + } + return sb.ToString(); + } + /// /// Finds a player and gets IP as string /// diff --git a/TerrariaServerBins/TerrariaServer.exe b/TerrariaServerBins/TerrariaServer.exe index d24449e7..f5226745 100644 Binary files a/TerrariaServerBins/TerrariaServer.exe and b/TerrariaServerBins/TerrariaServer.exe differ