diff --git a/DBEditor/CommandList.cs b/DBEditor/CommandList.cs index 1318fa5c..4b47951a 100644 --- a/DBEditor/CommandList.cs +++ b/DBEditor/CommandList.cs @@ -42,8 +42,6 @@ namespace TShockDBEditor CommandList.Add("annoy"); CommandList.Add("immunetokick"); CommandList.Add("immunetoban"); - CommandList.Add("ignorecheatdetection"); - CommandList.Add("ignoregriefdetection"); CommandList.Add("usebanneditem"); foreach (string command in CommandList) diff --git a/DBEditor/Main.cs b/DBEditor/Main.cs index d5a98e2c..180d779b 100644 --- a/DBEditor/Main.cs +++ b/DBEditor/Main.cs @@ -7,7 +7,7 @@ using System.Linq; using System.Text; using System.IO; using System.Security.Cryptography; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using MySql.Data.MySqlClient; using System.Windows.Forms; diff --git a/DBEditor/TShockDBEditor.csproj b/DBEditor/TShockDBEditor.csproj index 3d95e73b..ac8260c1 100644 --- a/DBEditor/TShockDBEditor.csproj +++ b/DBEditor/TShockDBEditor.csproj @@ -26,6 +26,7 @@ true 0 1.0.0.%2a + false false true @@ -49,8 +50,8 @@ 4 - - ..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll + + ..\SqlBins\Mono.Data.Sqlite.dll False diff --git a/SqlBins/Community.CsharpSqlite.SQLiteClient.dll b/SqlBins/Community.CsharpSqlite.SQLiteClient.dll deleted file mode 100644 index 269f3f98..00000000 Binary files a/SqlBins/Community.CsharpSqlite.SQLiteClient.dll and /dev/null differ diff --git a/SqlBins/Community.CsharpSqlite.dll b/SqlBins/Community.CsharpSqlite.dll deleted file mode 100644 index 2f69364b..00000000 Binary files a/SqlBins/Community.CsharpSqlite.dll and /dev/null differ diff --git a/SqlBins/Mono.Data.Sqlite.dll b/SqlBins/Mono.Data.Sqlite.dll new file mode 100644 index 00000000..ce600dbc Binary files /dev/null and b/SqlBins/Mono.Data.Sqlite.dll differ diff --git a/SqlBins/MySql.Data.dll b/SqlBins/MySql.Data.dll index 2f84ad9a..da3babd9 100644 Binary files a/SqlBins/MySql.Data.dll and b/SqlBins/MySql.Data.dll differ diff --git a/SqlBins/MySql.Web.dll b/SqlBins/MySql.Web.dll index e815a772..dc69aff8 100644 Binary files a/SqlBins/MySql.Web.dll and b/SqlBins/MySql.Web.dll differ diff --git a/SqlBins/sqlite3.def b/SqlBins/sqlite3.def new file mode 100644 index 00000000..3da3804f --- /dev/null +++ b/SqlBins/sqlite3.def @@ -0,0 +1,196 @@ +EXPORTS +sqlite3_aggregate_context +sqlite3_aggregate_count +sqlite3_auto_extension +sqlite3_backup_finish +sqlite3_backup_init +sqlite3_backup_pagecount +sqlite3_backup_remaining +sqlite3_backup_step +sqlite3_bind_blob +sqlite3_bind_double +sqlite3_bind_int +sqlite3_bind_int64 +sqlite3_bind_null +sqlite3_bind_parameter_count +sqlite3_bind_parameter_index +sqlite3_bind_parameter_name +sqlite3_bind_text +sqlite3_bind_text16 +sqlite3_bind_value +sqlite3_bind_zeroblob +sqlite3_blob_bytes +sqlite3_blob_close +sqlite3_blob_open +sqlite3_blob_read +sqlite3_blob_reopen +sqlite3_blob_write +sqlite3_busy_handler +sqlite3_busy_timeout +sqlite3_changes +sqlite3_clear_bindings +sqlite3_close +sqlite3_collation_needed +sqlite3_collation_needed16 +sqlite3_column_blob +sqlite3_column_bytes +sqlite3_column_bytes16 +sqlite3_column_count +sqlite3_column_database_name +sqlite3_column_database_name16 +sqlite3_column_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_origin_name +sqlite3_column_origin_name16 +sqlite3_column_table_name +sqlite3_column_table_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_column_value +sqlite3_commit_hook +sqlite3_compileoption_get +sqlite3_compileoption_used +sqlite3_complete +sqlite3_complete16 +sqlite3_config +sqlite3_context_db_handle +sqlite3_create_collation +sqlite3_create_collation16 +sqlite3_create_collation_v2 +sqlite3_create_function +sqlite3_create_function16 +sqlite3_create_function_v2 +sqlite3_create_module +sqlite3_create_module_v2 +sqlite3_data_count +sqlite3_db_config +sqlite3_db_handle +sqlite3_db_mutex +sqlite3_db_status +sqlite3_declare_vtab +sqlite3_enable_load_extension +sqlite3_enable_shared_cache +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_exec +sqlite3_expired +sqlite3_extended_errcode +sqlite3_extended_result_codes +sqlite3_file_control +sqlite3_finalize +sqlite3_free +sqlite3_free_table +sqlite3_get_autocommit +sqlite3_get_auxdata +sqlite3_get_table +sqlite3_global_recover +sqlite3_initialize +sqlite3_interrupt +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_libversion_number +sqlite3_limit +sqlite3_load_extension +sqlite3_log +sqlite3_malloc +sqlite3_memory_alarm +sqlite3_memory_highwater +sqlite3_memory_used +sqlite3_mprintf +sqlite3_mutex_alloc +sqlite3_mutex_enter +sqlite3_mutex_free +sqlite3_mutex_leave +sqlite3_mutex_try +sqlite3_next_stmt +sqlite3_open +sqlite3_open16 +sqlite3_open_v2 +sqlite3_os_end +sqlite3_os_init +sqlite3_overload_function +sqlite3_prepare +sqlite3_prepare16 +sqlite3_prepare16_v2 +sqlite3_prepare_v2 +sqlite3_profile +sqlite3_progress_handler +sqlite3_randomness +sqlite3_realloc +sqlite3_release_memory +sqlite3_reset +sqlite3_reset_auto_extension +sqlite3_result_blob +sqlite3_result_double +sqlite3_result_error +sqlite3_result_error16 +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig +sqlite3_result_int +sqlite3_result_int64 +sqlite3_result_null +sqlite3_result_text +sqlite3_result_text16 +sqlite3_result_text16be +sqlite3_result_text16le +sqlite3_result_value +sqlite3_result_zeroblob +sqlite3_rollback_hook +sqlite3_rtree_geometry_callback +sqlite3_set_authorizer +sqlite3_set_auxdata +sqlite3_shutdown +sqlite3_sleep +sqlite3_snprintf +sqlite3_soft_heap_limit +sqlite3_soft_heap_limit64 +sqlite3_sourceid +sqlite3_sql +sqlite3_status +sqlite3_step +sqlite3_stmt_readonly +sqlite3_stmt_status +sqlite3_strnicmp +sqlite3_table_column_metadata +sqlite3_test_control +sqlite3_thread_cleanup +sqlite3_threadsafe +sqlite3_total_changes +sqlite3_trace +sqlite3_transfer_bindings +sqlite3_update_hook +sqlite3_uri_parameter +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_numeric_type +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_vfs_find +sqlite3_vfs_register +sqlite3_vfs_unregister +sqlite3_vmprintf +sqlite3_vsnprintf +sqlite3_vtab_config +sqlite3_vtab_on_conflict +sqlite3_wal_autocheckpoint +sqlite3_wal_checkpoint +sqlite3_wal_checkpoint_v2 +sqlite3_wal_hook +sqlite3_win32_mbcs_to_utf8 +sqlite3_win32_utf8_to_mbcs diff --git a/SqlBins/sqlite3.dll b/SqlBins/sqlite3.dll new file mode 100644 index 00000000..0c2371bd Binary files /dev/null and b/SqlBins/sqlite3.dll differ diff --git a/Terraria.sln b/TShock.sln similarity index 100% rename from Terraria.sln rename to TShock.sln diff --git a/TShockAPI/BackupManager.cs b/TShockAPI/BackupManager.cs index 127fb185..857570ef 100644 --- a/TShockAPI/BackupManager.cs +++ b/TShockAPI/BackupManager.cs @@ -64,9 +64,9 @@ namespace TShockAPI if (worldpath != null && !Directory.Exists(worldpath)) Directory.CreateDirectory(worldpath); - Tools.Broadcast("Server map saving, potential lag spike"); + TShock.Utils.Broadcast("Server map saving, potential lag spike"); Console.WriteLine("Backing up world..."); - Thread SaveWorld = new Thread(Tools.SaveWorld); + Thread SaveWorld = new Thread(TShock.Utils.SaveWorld); SaveWorld.Start(); while (SaveWorld.ThreadState == ThreadState.Running) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index fed39020..5703cdc1 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -125,12 +125,17 @@ namespace TShockAPI add(Permissions.maintenance, CheckUpdates, "checkupdates"); add(Permissions.causeevents, DropMeteor, "dropmeteor"); add(Permissions.causeevents, Star, "star"); + add(Permissions.causeevents, Fullmoon, "fullmoon"); add(Permissions.causeevents, Bloodmoon, "bloodmoon"); add(Permissions.causeevents, Invade, "invade"); add(Permissions.spawnboss, Eater, "eater"); add(Permissions.spawnboss, Eye, "eye"); add(Permissions.spawnboss, King, "king"); add(Permissions.spawnboss, Skeletron, "skeletron"); + add(Permissions.spawnboss, WoF, "wof", "wallofflesh"); + add(Permissions.spawnboss, Twins, "twins"); + add(Permissions.spawnboss, Destroyer, "destroyer"); + add(Permissions.spawnboss, SkeletronPrime, "skeletronp", "prime"); add(Permissions.spawnboss, Hardcore, "hardcore"); add(Permissions.spawnmob, SpawnMob, "spawnmob", "sm"); add(Permissions.tp, Home, "home"); @@ -138,6 +143,7 @@ namespace TShockAPI add(Permissions.tp, TP, "tp"); add(Permissions.tphere, TPHere, "tphere"); add(Permissions.tphere, SendWarp, "sendwarp", "sw"); + add(Permissions.tpallow, TPAllow, "tpallow"); add(Permissions.warp, UseWarp, "warp"); add(Permissions.managewarp, SetWarp, "setwarp"); add(Permissions.managewarp, DeleteWarp, "delwarp"); @@ -149,7 +155,6 @@ namespace TShockAPI add(Permissions.manageitem, DeleteItem, "delitem"); add(Permissions.cfg, SetSpawn, "setspawn"); add(Permissions.cfg, Reload, "reload"); - add(Permissions.cfg, ShowConfiguration, "showconfig"); add(Permissions.cfg, ServerPassword, "serverpassword"); add(Permissions.cfg, Save, "save"); add(Permissions.cfg, Settle, "settle"); @@ -189,6 +194,11 @@ namespace TShockAPI add(Permissions.buff, Buff, "buff"); add(Permissions.buffplayer, GBuff, "gbuff", "buffplayer"); add(Permissions.grow, Grow, "grow"); + add(Permissions.hardmode, StartHardMode, "hardmode"); + add(Permissions.hardmode, DisableHardMode, "stophardmode", "disablehardmode"); + add(Permissions.cfg, ServerInfo, "stats"); + add(Permissions.converthardmode, ConvertCorruption, "convertcorruption"); + add(Permissions.converthardmode, ConvertHallow, "converthallow"); } public static bool HandleCommand(TSPlayer player, string text) @@ -209,13 +219,13 @@ namespace TShockAPI if (!cmd.CanRun(player)) { - Tools.SendLogs(string.Format("{0} tried to execute {1}", player.Name, cmd.Name), Color.Red); + TShock.Utils.SendLogs(string.Format("{0} tried to execute {1}", player.Name, cmd.Name), Color.Red); player.SendMessage("You do not have access to that command.", Color.Red); } else { if (cmd.DoLog) - Tools.SendLogs(string.Format("{0} executed: /{1}", player.Name, cmdText), Color.Red); + TShock.Utils.SendLogs(string.Format("{0} executed: /{1}", player.Name, cmdText), Color.Red); cmd.Run(cmdText, player, args); } return true; @@ -311,7 +321,7 @@ namespace TShockAPI if (args.Player.LoginAttempts > TShock.Config.MaximumLoginAttempts && (TShock.Config.MaximumLoginAttempts != -1)) { Log.Warn(args.Player.IP + "(" + args.Player.Name + ") had " + TShock.Config.MaximumLoginAttempts + " or more invalid login attempts and was kicked automatically."); - Tools.Kick(args.Player, "Too many invalid login attempts."); + TShock.Utils.Kick(args.Player, "Too many invalid login attempts."); } if (args.Parameters.Count != 2) @@ -322,7 +332,7 @@ namespace TShockAPI } try { - string encrPass = Tools.HashPassword(args.Parameters[1]); + string encrPass = TShock.Utils.HashPassword(args.Parameters[1]); var user = TShock.Users.GetUserByName(args.Parameters[0]); if (user == null) { @@ -330,10 +340,26 @@ namespace TShockAPI } else if (user.Password.ToUpper() == encrPass.ToUpper()) { - args.Player.Group = Tools.GetGroup(user.Group); + args.Player.PlayerData = TShock.InventoryDB.GetPlayerData(args.Player, TShock.Users.GetUserID(args.Parameters[0])); + + if (TShock.Config.ServerSideInventory) + { + if (!TShock.CheckInventory(args.Player)) + { + args.Player.SendMessage("Login Failed, Please fix the above errors then log back in.", Color.Cyan); + return; + } + } + + args.Player.Group = TShock.Utils.GetGroup(user.Group); args.Player.UserAccountName = args.Parameters[0]; args.Player.UserID = TShock.Users.GetUserID(args.Player.UserAccountName); args.Player.IsLoggedIn = true; + args.Player.IgnoreActionsForInventory = false; + + args.Player.PlayerData.CopyInventory(args.Player); + TShock.InventoryDB.InsertPlayerData(args.Player, args.Player.UserID); + args.Player.SendMessage("Authenticated as " + args.Parameters[0] + " successfully.", Color.LimeGreen); Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user: " + args.Parameters[0]); } @@ -359,7 +385,7 @@ namespace TShockAPI if (args.Player.IsLoggedIn && args.Parameters.Count == 2) { var user = TShock.Users.GetUserByName(args.Player.UserAccountName); - string encrPass = Tools.HashPassword(args.Parameters[0]); + string encrPass = TShock.Utils.HashPassword(args.Parameters[0]); if (user.Password.ToUpper() == encrPass.ToUpper()) { args.Player.SendMessage("You changed your password!", Color.Green); @@ -589,10 +615,21 @@ namespace TShockAPI } #endregion + #region Stupid commands + public static void ServerInfo(CommandArgs args) + { + args.Player.SendMessage("Memory usage: " + System.Diagnostics.Process.GetCurrentProcess().WorkingSet64); + args.Player.SendMessage("Allocated memory: " + System.Diagnostics.Process.GetCurrentProcess().VirtualMemorySize64); + args.Player.SendMessage("Total processor time: " + System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime); + args.Player.SendMessage("Ver: " + System.Environment.OSVersion); + args.Player.SendMessage("Proc count: " + System.Environment.ProcessorCount); + args.Player.SendMessage("Machine name: " + System.Environment.MachineName); + } + #endregion - #region Player Management Commands + #region Player Management Commands - private static void GrabUserUserInfo(CommandArgs args) + private static void GrabUserUserInfo(CommandArgs args) { if (args.Parameters.Count < 1) { @@ -600,7 +637,7 @@ namespace TShockAPI return; } - var players = Tools.FindPlayer(args.Parameters[0]); + var players = TShock.Utils.FindPlayer(args.Parameters[0]); if (players.Count > 1) { args.Player.SendMessage("More than one player matched your query.", Color.Red); @@ -630,7 +667,7 @@ namespace TShockAPI } string plStr = args.Parameters[0]; - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -642,7 +679,7 @@ namespace TShockAPI else { string reason = args.Parameters.Count > 1 ? String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1)) : "Misbehaviour."; - if (!Tools.Kick(players[0], reason)) + if (!TShock.Utils.Kick(players[0], reason)) { args.Player.SendMessage("You can't kick another admin!", Color.Red); } @@ -663,7 +700,7 @@ namespace TShockAPI } string plStr = args.Parameters[0]; - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -675,7 +712,7 @@ namespace TShockAPI else { string reason = args.Parameters.Count > 1 ? String.Join(" ", args.Parameters.GetRange(1, args.Parameters.Count - 1)) : "Misbehaviour."; - if (!Tools.Ban(players[0], reason)) + if (!TShock.Utils.Ban(players[0], reason)) { args.Player.SendMessage("You can't ban another admin!", Color.Red); } @@ -856,20 +893,20 @@ namespace TShockAPI message += " " + args.Parameters[i]; } - Tools.Broadcast("(Server Broadcast)" + message, Color.Red); + TShock.Utils.Broadcast("(Server Broadcast)" + message, Color.Red); return; } private static void Off(CommandArgs args) { - Tools.ForceKickAll("Server shutting down!"); + TShock.Utils.ForceKickAll("Server shutting down!"); WorldGen.saveWorld(); Netplay.disconnect = true; } private static void OffNoSave(CommandArgs args) { - Tools.ForceKickAll("Server shutting down!"); + TShock.Utils.ForceKickAll("Server shutting down!"); Netplay.disconnect = true; } @@ -906,7 +943,7 @@ namespace TShockAPI Process.Start(new ProcessStartInfo("UpdateTShock.exe")); - Tools.ForceKickAll("Server shutting down for update!"); + TShock.Utils.ForceKickAll("Server shutting down for update!"); WorldGen.saveWorld(); Netplay.disconnect = true; } @@ -936,23 +973,29 @@ namespace TShockAPI speedY *= penis61; Projectile.NewProjectile(vector.X, vector.Y, speedX, speedY, 12, 0x3e8, 10f, Main.myPlayer); } + + private static void Fullmoon(CommandArgs args) + { + TSPlayer.Server.SetFullMoon(true); + TShock.Utils.Broadcast(string.Format("{0} turned on full moon.", args.Player.Name)); + } private static void Bloodmoon(CommandArgs args) { TSPlayer.Server.SetBloodMoon(true); - Tools.Broadcast(string.Format("{0} turned on blood moon.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} turned on blood moon.", args.Player.Name)); } private static void Invade(CommandArgs args) { if (Main.invasionSize <= 0) { - Tools.Broadcast(string.Format("{0} has started an invasion.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} has started an invasion.", args.Player.Name)); TShock.StartInvasion(); } else { - Tools.Broadcast(string.Format("{0} has ended an invasion.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} has ended an invasion.", args.Player.Name)); Main.invasionSize = 0; } } @@ -971,9 +1014,9 @@ namespace TShockAPI return; } amount = Math.Min(amount, Main.maxNPCs); - NPC eater = Tools.GetNPCById(13); + NPC eater = TShock.Utils.GetNPCById(13); TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, args.Player.TileX, args.Player.TileY); - Tools.Broadcast(string.Format("{0} has spawned eater of worlds {1} times!", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} has spawned eater of worlds {1} times!", args.Player.Name, amount)); } private static void Eye(CommandArgs args) @@ -990,10 +1033,10 @@ namespace TShockAPI return; } amount = Math.Min(amount, Main.maxNPCs); - NPC eye = Tools.GetNPCById(4); + NPC eye = TShock.Utils.GetNPCById(4); TSPlayer.Server.SetTime(false, 0.0); TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, args.Player.TileX, args.Player.TileY); - Tools.Broadcast(string.Format("{0} has spawned eye {1} times!", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} has spawned eye {1} times!", args.Player.Name, amount)); } private static void King(CommandArgs args) @@ -1010,9 +1053,9 @@ namespace TShockAPI return; } amount = Math.Min(amount, Main.maxNPCs); - NPC king = Tools.GetNPCById(50); + NPC king = TShock.Utils.GetNPCById(50); TSPlayer.Server.SpawnNPC(king.type, king.name, amount, args.Player.TileX, args.Player.TileY); - Tools.Broadcast(string.Format("{0} has spawned king slime {1} times!", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} has spawned king slime {1} times!", args.Player.Name, amount)); } private static void Skeletron(CommandArgs args) @@ -1029,13 +1072,86 @@ namespace TShockAPI return; } amount = Math.Min(amount, Main.maxNPCs); - NPC skeletron = Tools.GetNPCById(35); + NPC skeletron = TShock.Utils.GetNPCById(35); TSPlayer.Server.SetTime(false, 0.0); TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, args.Player.TileX, args.Player.TileY); - Tools.Broadcast(string.Format("{0} has spawned skeletron {1} times!", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} has spawned skeletron {1} times!", args.Player.Name, amount)); } - private static void Hardcore(CommandArgs args) + private static void WoF(CommandArgs args) + { + if (Main.wof >= 0 || (args.Player.Y / 16f < (float)(Main.maxTilesY - 205))) + { + args.Player.SendMessage("Can't spawn Wall of Flesh!", Color.Red); + return; + } + NPC.SpawnWOF(new Vector2(args.Player.X, args.Player.Y)); + TShock.Utils.Broadcast(string.Format("{0} has spawned Wall of Flesh!", args.Player.Name)); + } + + private static void Twins(CommandArgs args) + { + if (args.Parameters.Count > 1) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /twins [amount]", Color.Red); + return; + } + int amount = 1; + if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount)) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /twins [amount]", Color.Red); + return; + } + amount = Math.Min(amount, Main.maxNPCs); + NPC retinazer = TShock.Utils.GetNPCById(125); + NPC spaz = TShock.Utils.GetNPCById(126); + TSPlayer.Server.SetTime(false, 0.0); + TSPlayer.Server.SpawnNPC(retinazer.type, retinazer.name, amount, args.Player.TileX, args.Player.TileY); + TSPlayer.Server.SpawnNPC(spaz.type, spaz.name, amount, args.Player.TileX, args.Player.TileY); + TShock.Utils.Broadcast(string.Format("{0} has spawned the twins {1} times!", args.Player.Name, amount)); + } + + private static void Destroyer(CommandArgs args) + { + if (args.Parameters.Count > 1) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /destroyer [amount]", Color.Red); + return; + } + int amount = 1; + if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount)) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /destroyer [amount]", Color.Red); + return; + } + amount = Math.Min(amount, Main.maxNPCs); + NPC destroyer = TShock.Utils.GetNPCById(134); + TSPlayer.Server.SetTime(false, 0.0); + TSPlayer.Server.SpawnNPC(destroyer.type, destroyer.name, amount, args.Player.TileX, args.Player.TileY); + TShock.Utils.Broadcast(string.Format("{0} has spawned the destroyer {1} times!", args.Player.Name, amount)); + } + + private static void SkeletronPrime(CommandArgs args) + { + if (args.Parameters.Count > 1) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /prime [amount]", Color.Red); + return; + } + int amount = 1; + if (args.Parameters.Count == 1 && !int.TryParse(args.Parameters[0], out amount)) + { + args.Player.SendMessage("Invalid syntax! Proper syntax: /prime [amount]", Color.Red); + return; + } + amount = Math.Min(amount, Main.maxNPCs); + NPC prime = TShock.Utils.GetNPCById(127); + TSPlayer.Server.SetTime(false, 0.0); + TSPlayer.Server.SpawnNPC(prime.type, prime.name, amount, args.Player.TileX, args.Player.TileY); + TShock.Utils.Broadcast(string.Format("{0} has spawned skeletron prime {1} times!", args.Player.Name, amount)); + } + + private static void Hardcore(CommandArgs args) // TODO: Add all 8 bosses { if (args.Parameters.Count > 1) { @@ -1049,16 +1165,24 @@ namespace TShockAPI return; } amount = Math.Min(amount, Main.maxNPCs / 4); - NPC eater = Tools.GetNPCById(13); - NPC eye = Tools.GetNPCById(4); - NPC king = Tools.GetNPCById(50); - NPC skeletron = Tools.GetNPCById(35); + NPC retinazer = TShock.Utils.GetNPCById(125); + NPC spaz = TShock.Utils.GetNPCById(126); + NPC destroyer = TShock.Utils.GetNPCById(134); + NPC prime = TShock.Utils.GetNPCById(127); + NPC eater = TShock.Utils.GetNPCById(13); + NPC eye = TShock.Utils.GetNPCById(4); + NPC king = TShock.Utils.GetNPCById(50); + NPC skeletron = TShock.Utils.GetNPCById(35); TSPlayer.Server.SetTime(false, 0.0); + TSPlayer.Server.SpawnNPC(retinazer.type, retinazer.name, amount, args.Player.TileX, args.Player.TileY); + TSPlayer.Server.SpawnNPC(spaz.type, spaz.name, amount, args.Player.TileX, args.Player.TileY); + TSPlayer.Server.SpawnNPC(destroyer.type, destroyer.name, amount, args.Player.TileX, args.Player.TileY); + TSPlayer.Server.SpawnNPC(prime.type, prime.name, amount, args.Player.TileX, args.Player.TileY); TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, args.Player.TileX, args.Player.TileY); TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, args.Player.TileX, args.Player.TileY); TSPlayer.Server.SpawnNPC(king.type, king.name, amount, args.Player.TileX, args.Player.TileY); TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, args.Player.TileX, args.Player.TileY); - Tools.Broadcast(string.Format("{0} has spawned all bosses {1} times!", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} has spawned all bosses {1} times!", args.Player.Name, amount)); } private static void SpawnMob(CommandArgs args) @@ -1082,7 +1206,7 @@ namespace TShockAPI amount = Math.Min(amount, Main.maxNPCs); - var npcs = Tools.GetNPCByIdOrName(args.Parameters[0]); + var npcs = TShock.Utils.GetNPCByIdOrName(args.Parameters[0]); if (npcs.Count == 0) { args.Player.SendMessage("Invalid mob type!", Color.Red); @@ -1094,16 +1218,86 @@ namespace TShockAPI else { var npc = npcs[0]; - if (npc.type >= 1 && npc.type < Main.maxNPCTypes) + if (npc.type >= 1 && npc.type < Main.maxNPCTypes && npc.type != 113) //Do not allow WoF to spawn, in certain conditions may cause loops in client { TSPlayer.Server.SpawnNPC(npc.type, npc.name, amount, args.Player.TileX, args.Player.TileY, 50, 20); - Tools.Broadcast(string.Format("{0} was spawned {1} time(s).", npc.name, amount)); + TShock.Utils.Broadcast(string.Format("{0} was spawned {1} time(s).", npc.name, amount)); } + else if (npc.type == 113) + args.Player.SendMessage("Sorry, you can't spawn Wall of Flesh! Try /wof instead."); // Maybe perhaps do something with WorldGen.SpawnWoF? else args.Player.SendMessage("Invalid mob type!", Color.Red); } } + private static void StartHardMode(CommandArgs args) + { + WorldGen.StartHardmode(); + } + + private static void DisableHardMode(CommandArgs args) + { + Main.hardMode = false; + } + + private static void ConvertCorruption(CommandArgs args) + { + TShock.Utils.Broadcast("Server is might lag for a moment.", Color.Red); + for (int x = 0; x < Main.maxTilesX; x++) + { + for (int y = 0; y < Main.maxTilesY; y++) + { + switch (Main.tile[x, y].type) + { + case 25: + Main.tile[x, y].type = 117; + break; + case 23: + Main.tile[x, y].type = 109; + break; + case 112: + Main.tile[x, y].type = 116; + break; + default: + continue; + } + } + } + WorldGen.CountTiles(0); + TSPlayer.All.SendData(PacketTypes.UpdateGoodEvil); + Netplay.ResetSections(); + TShock.Utils.Broadcast("Corruption conversion done."); + } + + private static void ConvertHallow(CommandArgs args) + { + TShock.Utils.Broadcast("Server is might lag for a moment.", Color.Red); + for (int x = 0; x < Main.maxTilesX; x++) + { + for (int y = 0; y < Main.maxTilesY; y++) + { + switch (Main.tile[x, y].type) + { + case 117: + Main.tile[x, y].type = 25; + break; + case 109: + Main.tile[x, y].type = 23; + break; + case 116: + Main.tile[x, y].type = 112; + break; + default: + continue; + } + } + } + WorldGen.CountTiles(0); + TSPlayer.All.SendData(PacketTypes.UpdateGoodEvil); + Netplay.ResetSections(); + TShock.Utils.Broadcast("Hallow conversion done."); + } + #endregion Cause Events and Spawn Monsters Commands #region Teleport Commands @@ -1147,16 +1341,26 @@ namespace TShockAPI } string plStr = String.Join(" ", args.Parameters); - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) args.Player.SendMessage("Invalid player!", Color.Red); else if (players.Count > 1) args.Player.SendMessage("More than one player matched!", Color.Red); + else if (!players[0].TPAllow && !args.Player.Group.HasPermission(Permissions.tpall)) + { + var plr = players[0]; + args.Player.SendMessage(plr.Name + " Has Selected For Users Not To Teleport To Them"); + plr.SendMessage(args.Player.Name + " Attempted To Teleport To You"); + } else { var plr = players[0]; if (args.Player.Teleport(plr.TileX, plr.TileY + 3)) + { args.Player.SendMessage(string.Format("Teleported to {0}", plr.Name)); + if(!args.Player.Group.HasPermission(Permissions.tphide)) + plr.SendMessage(args.Player.Name + " Teleported To You"); + } } } @@ -1190,7 +1394,7 @@ namespace TShockAPI return; } - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -1207,10 +1411,18 @@ namespace TShockAPI plr.SendMessage(string.Format("You were teleported to {0}.", args.Player.Name)); args.Player.SendMessage(string.Format("You brought {0} here.", plr.Name)); } - } } + private static void TPAllow(CommandArgs args) + { + if (!args.Player.TPAllow) + args.Player.SendMessage("Other Players Can Now Teleport To You"); + if (args.Player.TPAllow) + args.Player.SendMessage("Other Players Can No Longer Teleport To You"); + args.Player.TPAllow = !args.Player.TPAllow; + } + private static void SendWarp(CommandArgs args) { if (args.Parameters.Count < 2) @@ -1219,7 +1431,7 @@ namespace TShockAPI return; } - var foundplr = Tools.FindPlayer(args.Parameters[0]); + var foundplr = TShock.Utils.FindPlayer(args.Parameters[0]); if (foundplr.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -1458,7 +1670,7 @@ namespace TShockAPI { if (args.Parameters.Count > 0) { - var items = Tools.GetItemByIdOrName(args.Parameters[0]); + var items = TShock.Utils.GetItemByIdOrName(args.Parameters[0]); if (items.Count == 0) { args.Player.SendMessage("Invalid item type!", Color.Red); @@ -1491,7 +1703,7 @@ namespace TShockAPI { if (args.Parameters.Count > 0) { - var items = Tools.GetItemByIdOrName(args.Parameters[0]); + var items = TShock.Utils.GetItemByIdOrName(args.Parameters[0]); if (items.Count == 0) { args.Player.SendMessage("Invalid item type!", Color.Red); @@ -1529,38 +1741,17 @@ namespace TShockAPI Main.spawnTileX = args.Player.TileX + 1; Main.spawnTileY = args.Player.TileY + 3; - Tools.Broadcast("Server map saving, potential lag spike"); - Thread SaveWorld = new Thread(Tools.SaveWorld); + TShock.Utils.Broadcast("Server map saving, potential lag spike"); + Thread SaveWorld = new Thread(TShock.Utils.SaveWorld); SaveWorld.Start(); } - private static void ShowConfiguration(CommandArgs args) - { - args.Player.SendMessage("TShock Config:"); - string lineOne = string.Format("BanCheater : {0}, KickCheater : {1}, BanGriefer : {2}, KickGriefer : {3}", - TShock.Config.BanCheaters, TShock.Config.KickCheaters, - TShock.Config.BanGriefers, TShock.Config.KickGriefers); - args.Player.SendMessage(lineOne, Color.Yellow); - string lineTwo = string.Format("BanTnt : {0}, KickTnt : {1}, BanBoom : {2}, KickBoom : {3}", - TShock.Config.BanKillTileAbusers, TShock.Config.KickKillTileAbusers, - TShock.Config.BanExplosives, TShock.Config.KickExplosives); - args.Player.SendMessage(lineTwo, Color.Yellow); - string lineThree = string.Format("RangeChecks : {0}, DisableBuild : {1}, ProtectSpawn : {2}, ProtectRadius : {3}", - TShock.Config.RangeChecks, TShock.Config.DisableBuild, - TShock.Config.SpawnProtection, TShock.Config.SpawnProtectionRadius); - args.Player.SendMessage(lineThree, Color.Yellow); - string lineFour = string.Format("MaxSlots : {0}, SpamChecks : {1}, InvMultiplier : {2}, DMS : {3}, SpawnRate {4}", - TShock.Config.MaxSlots, TShock.Config.SpamChecks, - TShock.Config.InvasionMultiplier, TShock.Config.DefaultMaximumSpawns, - TShock.Config.DefaultSpawnRate); - args.Player.SendMessage(lineFour, Color.Yellow); - } - private static void Reload(CommandArgs args) { FileTools.SetupConfig(); TShock.Groups.LoadPermisions(); - args.Player.SendMessage("Configuration & Permissions reload complete. Some changes may require server restart."); + TShock.Regions.ReloadAllRegions(); + args.Player.SendMessage("Configuration, Permissions, and Regions reload complete. Some changes may require server restart."); } private static void ServerPassword(CommandArgs args) @@ -1577,8 +1768,8 @@ namespace TShockAPI private static void Save(CommandArgs args) { - Tools.Broadcast("Server map saving, potential lag spike"); - Thread SaveWorld = new Thread(Tools.SaveWorld); + TShock.Utils.Broadcast("Server map saving, potential lag spike"); + Thread SaveWorld = new Thread(TShock.Utils.SaveWorld); SaveWorld.Start(); } @@ -1591,7 +1782,7 @@ namespace TShockAPI return; } Liquid.StartPanic(); - Tools.Broadcast("Settling all liquids..."); + TShock.Utils.Broadcast("Settling all liquids..."); } @@ -1607,7 +1798,7 @@ namespace TShockAPI int.TryParse(args.Parameters[0], out amount); NPC.defaultMaxSpawns = amount; TShock.Config.DefaultMaximumSpawns = amount; - Tools.Broadcast(string.Format("{0} changed the maximum spawns to: {1}", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} changed the maximum spawns to: {1}", args.Player.Name, amount)); } private static void SpawnRate(CommandArgs args) @@ -1622,7 +1813,7 @@ namespace TShockAPI int.TryParse(args.Parameters[0], out amount); NPC.defaultSpawnRate = amount; TShock.Config.DefaultSpawnRate = amount; - Tools.Broadcast(string.Format("{0} changed the spawn rate to: {1}", args.Player.Name, amount)); + TShock.Utils.Broadcast(string.Format("{0} changed the spawn rate to: {1}", args.Player.Name, amount)); } #endregion Server Config Commands @@ -1641,23 +1832,23 @@ namespace TShockAPI { case "day": TSPlayer.Server.SetTime(true, 150.0); - Tools.Broadcast(string.Format("{0} set time to day.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} set time to day.", args.Player.Name)); break; case "night": TSPlayer.Server.SetTime(false, 0.0); - Tools.Broadcast(string.Format("{0} set time to night.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} set time to night.", args.Player.Name)); break; case "dusk": TSPlayer.Server.SetTime(false, 0.0); - Tools.Broadcast(string.Format("{0} set time to dusk.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} set time to dusk.", args.Player.Name)); break; case "noon": TSPlayer.Server.SetTime(true, 27000.0); - Tools.Broadcast(string.Format("{0} set time to noon.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} set time to noon.", args.Player.Name)); break; case "midnight": TSPlayer.Server.SetTime(false, 16200.0); - Tools.Broadcast(string.Format("{0} set time to midnight.", args.Player.Name)); + TShock.Utils.Broadcast(string.Format("{0} set time to midnight.", args.Player.Name)); break; default: args.Player.SendMessage("Invalid syntax! Proper syntax: /time ", Color.Red); @@ -1679,7 +1870,7 @@ namespace TShockAPI } string plStr = args.Parameters[0]; - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -1698,10 +1889,10 @@ namespace TShockAPI } if (!args.Player.Group.HasPermission(Permissions.kill)) { - damage = Tools.Clamp(damage, 15, 0); + damage = TShock.Utils.Clamp(damage, 15, 0); } plr.DamagePlayer(damage); - Tools.Broadcast(string.Format("{0} slapped {1} for {2} damage.", + TShock.Utils.Broadcast(string.Format("{0} slapped {1} for {2} damage.", args.Player.Name, plr.Name, damage)); Log.Info(args.Player.Name + " slapped " + plr.Name + " with " + damage + " damage."); } @@ -1714,13 +1905,13 @@ namespace TShockAPI private static void ToggleAntiBuild(CommandArgs args) { TShock.Config.DisableBuild = (TShock.Config.DisableBuild == false); - Tools.Broadcast(string.Format("Anti-build is now {0}.", (TShock.Config.DisableBuild ? "on" : "off"))); + TShock.Utils.Broadcast(string.Format("Anti-build is now {0}.", (TShock.Config.DisableBuild ? "on" : "off"))); } private static void ProtectSpawn(CommandArgs args) { TShock.Config.SpawnProtection = (TShock.Config.SpawnProtection == false); - Tools.Broadcast(string.Format("Spawn is now {0}.", (TShock.Config.SpawnProtection ? "protected" : "open"))); + TShock.Utils.Broadcast(string.Format("Spawn is now {0}.", (TShock.Config.SpawnProtection ? "protected" : "open"))); } private static void DebugRegions(CommandArgs args) @@ -2012,7 +2203,7 @@ namespace TShockAPI if (args.Parameters.Count == 4) { int direction; - switch (args.Parameters[3]) + switch (args.Parameters[2]) { case "u": case "up": @@ -2045,7 +2236,7 @@ namespace TShockAPI } } int addAmount; - int.TryParse(args.Parameters[2], out addAmount); + int.TryParse(args.Parameters[3], out addAmount); if (TShock.Regions.resizeRegion(args.Parameters[1], addAmount, direction)) { args.Player.SendMessage("Region Resized Successfully!", Color.Yellow); @@ -2122,7 +2313,7 @@ namespace TShockAPI private static void Playing(CommandArgs args) { - args.Player.SendMessage(string.Format("Current players: {0}.", Tools.GetPlayers()), 255, 240, 20); + args.Player.SendMessage(string.Format("Current players: {0}.", TShock.Utils.GetPlayers()), 255, 240, 20); } private static void AuthToken(CommandArgs args) @@ -2139,7 +2330,7 @@ namespace TShockAPI try { TShock.Users.AddUser(new User(args.Player.IP, "", "", "superadmin")); - args.Player.Group = Tools.GetGroup("superadmin"); + args.Player.Group = TShock.Utils.GetGroup("superadmin"); args.Player.SendMessage("This IP address is now superadmin. Please perform the following command:"); args.Player.SendMessage("/user add : superadmin"); args.Player.SendMessage("Creates: with the password as part of the superadmin group."); @@ -2202,7 +2393,7 @@ namespace TShockAPI args.Player.SendMessage("Invalid syntax! Proper syntax: /me ", Color.Red); return; } - Tools.Broadcast(string.Format("*{0} {1}", args.Player.Name, String.Join(" ", args.Parameters)), 205, 133, 63); + TShock.Utils.Broadcast(string.Format("*{0} {1}", args.Player.Name, String.Join(" ", args.Parameters)), 205, 133, 63); } private static void PartyChat(CommandArgs args) @@ -2230,12 +2421,12 @@ namespace TShockAPI private static void Motd(CommandArgs args) { - Tools.ShowFileToUser(args.Player, "motd.txt"); + TShock.Utils.ShowFileToUser(args.Player, "motd.txt"); } private static void Rules(CommandArgs args) { - Tools.ShowFileToUser(args.Player, "rules.txt"); + TShock.Utils.ShowFileToUser(args.Player, "rules.txt"); } private static void Whisper(CommandArgs args) @@ -2246,7 +2437,7 @@ namespace TShockAPI return; } - var players = Tools.FindPlayer(args.Parameters[0]); + var players = TShock.Utils.FindPlayer(args.Parameters[0]); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -2288,7 +2479,7 @@ namespace TShockAPI int annoy = 5; int.TryParse(args.Parameters[1], out annoy); - var players = Tools.FindPlayer(args.Parameters[0]); + var players = TShock.Utils.FindPlayer(args.Parameters[0]); if (players.Count == 0) args.Player.SendMessage("Invalid player!", Color.Red); else if (players.Count > 1) @@ -2314,7 +2505,7 @@ namespace TShockAPI } string plStr = String.Join(" ", args.Parameters); - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -2347,20 +2538,20 @@ namespace TShockAPI int killcount = 0; for (int i = 0; i < Main.npc.Length; i++) { - if (Main.npc[i].active && !Main.npc[i].townNPC && (!Main.npc[i].friendly || killFriendly)) + if (Main.npc[i].active && Main.npc[i].type != 0 && !Main.npc[i].townNPC && (!Main.npc[i].friendly || killFriendly)) { TSPlayer.Server.StrikeNPC(i, 99999, 90f, 1); killcount++; } } - Tools.Broadcast(string.Format("Killed {0} NPCs.", killcount)); + TShock.Utils.Broadcast(string.Format("Killed {0} NPCs.", killcount)); } private static void Item(CommandArgs args) { if (args.Parameters.Count < 1) { - args.Player.SendMessage("Invalid syntax! Proper syntax: /item [item amount]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /item [item amount] [prefix id/name]", Color.Red); return; } if (args.Parameters[0].Length == 0) @@ -2369,8 +2560,17 @@ namespace TShockAPI return; } int itemAmount = 0; - int.TryParse(args.Parameters[args.Parameters.Count - 1], out itemAmount); - var items = Tools.GetItemByIdOrName(args.Parameters[0]); + int prefix = 0; + if (args.Parameters.Count == 2) + int.TryParse(args.Parameters[1], out itemAmount); + else if (args.Parameters.Count == 3) + { + int.TryParse(args.Parameters[1], out itemAmount); + var found = TShock.Utils.GetPrefixByIdOrName(args.Parameters[2]); + if (found.Count == 1) + prefix = found[0]; + } + var items = TShock.Utils.GetItemByIdOrName(args.Parameters[0]); if (items.Count == 0) { args.Player.SendMessage("Invalid item type!", Color.Red); @@ -2388,7 +2588,7 @@ namespace TShockAPI { if (itemAmount == 0 || itemAmount > item.maxStack) itemAmount = item.maxStack; - args.Player.GiveItem(item.type, item.name, item.width, item.height, itemAmount); + args.Player.GiveItem(item.type, item.name, item.width, item.height, itemAmount, prefix); args.Player.SendMessage(string.Format("Gave {0} {1}(s).", itemAmount, item.name)); } else @@ -2407,7 +2607,7 @@ namespace TShockAPI { if (args.Parameters.Count < 2) { - args.Player.SendMessage("Invalid syntax! Proper syntax: /give [item amount]", Color.Red); + args.Player.SendMessage("Invalid syntax! Proper syntax: /give [item amount] [prefix id/name]", Color.Red); return; } if (args.Parameters[0].Length == 0) @@ -2421,13 +2621,20 @@ namespace TShockAPI return; } int itemAmount = 0; - var items = Tools.GetItemByIdOrName(args.Parameters[0]); + int prefix = 0; + var items = TShock.Utils.GetItemByIdOrName(args.Parameters[0]); args.Parameters.RemoveAt(0); string plStr = args.Parameters[0]; args.Parameters.RemoveAt(0); - if (args.Parameters.Count > 0) - int.TryParse(args.Parameters[args.Parameters.Count - 1], out itemAmount); - + if (args.Parameters.Count == 1) + int.TryParse(args.Parameters[0], out itemAmount); + else if (args.Parameters.Count == 2) + { + int.TryParse(args.Parameters[0], out itemAmount); + var found = TShock.Utils.GetPrefixByIdOrName(args.Parameters[1]); + if (found.Count == 1) + prefix = found[0]; + } if (items.Count == 0) { @@ -2442,7 +2649,7 @@ namespace TShockAPI var item = items[0]; if (item.type >= 1 && item.type < Main.maxItemTypes) { - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -2458,7 +2665,7 @@ namespace TShockAPI { if (itemAmount == 0 || itemAmount > item.maxStack) itemAmount = item.maxStack; - plr.GiveItem(item.type, item.name, item.width, item.height, itemAmount); + plr.GiveItem(item.type, item.name, item.width, item.height, itemAmount, prefix); args.Player.SendMessage(string.Format("Gave {0} {1} {2}(s).", plr.Name, itemAmount, item.name)); plr.SendMessage(string.Format("{0} gave you {1} {2}(s).", args.Player.Name, itemAmount, item.name)); } @@ -2481,39 +2688,29 @@ namespace TShockAPI int radius = 50; if (args.Parameters.Count > 0) { - if (args.Parameters[0].ToLower() == "all") { - radius = Int32.MaxValue / 16; - } else { - try { - radius = Convert.ToInt32(args.Parameters[0]); - } catch (Exception) { args.Player.SendMessage("Please either enter the keyword \"all\", or the block radius you wish to delete all items from.", Color.Red); return; } - } } int count = 0; for (int i = 0; i < 200; i++) { - if ((Math.Sqrt(Math.Pow(Main.item[i].position.X - args.Player.X, 2) + Math.Pow(Main.item[i].position.Y - args.Player.Y, 2)) < radius * 16) && (Main.item[i].active)) { - Main.item[i].active = false; NetMessage.SendData(0x15, -1, -1, "", i, 0f, 0f, 0f, 0); count++; } - } args.Player.SendMessage("All " + count.ToString() + " items within a radius of " + radius.ToString() + " have been deleted."); @@ -2525,7 +2722,7 @@ namespace TShockAPI if (args.Parameters.Count > 0) { string plStr = String.Join(" ", args.Parameters); - var players = Tools.FindPlayer(plStr); + var players = TShock.Utils.FindPlayer(plStr); if (players.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -2551,8 +2748,8 @@ namespace TShockAPI playerToHeal = args.Player; } - Item heart = Tools.GetItemById(58); - Item star = Tools.GetItemById(184); + Item heart = TShock.Utils.GetItemById(58); + Item star = TShock.Utils.GetItemById(184); for (int i = 0; i < 20; i++) playerToHeal.GiveItem(heart.type, heart.name, heart.width, heart.height, heart.maxStack); for (int i = 0; i < 10; i++) @@ -2579,7 +2776,7 @@ namespace TShockAPI int time = 60; if (!int.TryParse(args.Parameters[0], out id)) { - var found = Tools.GetBuffByName(args.Parameters[0]); + var found = TShock.Utils.GetBuffByName(args.Parameters[0]); if (found.Count == 0) { args.Player.SendMessage("Invalid buff name!", Color.Red); @@ -2600,7 +2797,7 @@ namespace TShockAPI time = 60; args.Player.SetBuff(id, time * 60); args.Player.SendMessage(string.Format("You have buffed yourself with {0}({1}) for {2} seconds!", - Tools.GetBuffName(id), Tools.GetBuffDescription(id), (time)), Color.Green); + TShock.Utils.GetBuffName(id), TShock.Utils.GetBuffDescription(id), (time)), Color.Green); } else args.Player.SendMessage("Invalid buff ID!", Color.Red); @@ -2615,7 +2812,7 @@ namespace TShockAPI } int id = 0; int time = 60; - var foundplr = Tools.FindPlayer(args.Parameters[0]); + var foundplr = TShock.Utils.FindPlayer(args.Parameters[0]); if (foundplr.Count == 0) { args.Player.SendMessage("Invalid player!", Color.Red); @@ -2630,7 +2827,7 @@ namespace TShockAPI { if (!int.TryParse(args.Parameters[1], out id)) { - var found = Tools.GetBuffByName(args.Parameters[1]); + var found = TShock.Utils.GetBuffByName(args.Parameters[1]); if (found.Count == 0) { args.Player.SendMessage("Invalid buff name!", Color.Red); @@ -2651,9 +2848,9 @@ namespace TShockAPI time = 60; foundplr[0].SetBuff(id, time * 60); args.Player.SendMessage(string.Format("You have buffed {0} with {1}({2}) for {3} seconds!", - foundplr[0].Name, Tools.GetBuffName(id), Tools.GetBuffDescription(id), (time)), Color.Green); + foundplr[0].Name, TShock.Utils.GetBuffName(id), TShock.Utils.GetBuffDescription(id), (time)), Color.Green); foundplr[0].SendMessage(string.Format("{0} has buffed you with {1}({2}) for {3} seconds!", - args.Player.Name, Tools.GetBuffName(id), Tools.GetBuffDescription(id), (time)), Color.Green); + args.Player.Name, TShock.Utils.GetBuffName(id), TShock.Utils.GetBuffDescription(id), (time)), Color.Green); } else args.Player.SendMessage("Invalid buff ID!", Color.Red); diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs index 7a243147..4ec36764 100644 --- a/TShockAPI/ConfigFile.cs +++ b/TShockAPI/ConfigFile.cs @@ -30,9 +30,9 @@ namespace TShockAPI [Description("The equation for calculating invasion size is 100 + (multiplier * (number of active players with greater than 200 health))")] public int InvasionMultiplier = 1; [Description("The default maximum mobs that will spawn per wave. Higher means more mobs in that wave.")] - public int DefaultMaximumSpawns = 4; + public int DefaultMaximumSpawns = 5; [Description("The delay between waves. Shorter values lead to less mobs.")] - public int DefaultSpawnRate = 700; + public int DefaultSpawnRate = 600; [Description("The port the server runs on.")] public int ServerPort = 7777; [Description("Enable or disable the whitelist based on IP addresses in whitelist.txt")] @@ -40,49 +40,25 @@ namespace TShockAPI [Description("Enable the ability for invaison size to never decrease. Make sure to run /invade, and note that this adds 2 million+ goblins to the spawn que for the map.")] public bool InfiniteInvasion; [Description("Enable or disable perma pvp.")] - public bool AlwaysPvP; - [Description("Kicks players who edit save files for cheating.")] - public bool KickCheaters = true; - [Description("")] - public bool BanCheaters = true; - [Description("")] - public bool KickGriefers = true; - [Description("")] - public bool BanGriefers = true; - [Description("Bans players who attempt to kill tiles using TNT or exploits. Requires kick to be enabled.")] - public bool BanKillTileAbusers = true; - [Description("Kicks players who attempt to kill tiles using TNT or exploits.")] - public bool KickKillTileAbusers = true; - [Description("Bans players who attempt to throw a bomb or dynamite.")] - public bool BanExplosives = true; - [Description("Kicks players who attempt to throw a bomb or dynamite.")] - public bool KickExplosives = true; - [Description("Explosives won't break blocks")] - public bool DisableExplosives = true; + public bool AlwaysPvP = false; [Description("Prevents tiles from being placed within SpawnProtectionRadius of the default spawn.")] public bool SpawnProtection = true; [Description("Radius from spawn tile for SpawnProtection.")] - public int SpawnProtectionRadius = 5; + public int SpawnProtectionRadius = 10; [Description("Max slots for the server. If you want people to be kicked with \"Server is full\" set this to how many players you want max and then set Terraria max players to 2 higher.")] public int MaxSlots = 8; [Description("Global protection agent for any block distance based anti-grief check.")] public bool RangeChecks = true; - [Description("Enable/Disable Terrarias built in spam checks.")] - public bool SpamChecks; [Description("Disables any building; placing of blocks")] public bool DisableBuild; [Description("Kick a player if they exceed this number of tile kills within 1 second.")] - public int TileThreshold = 60; + public int TileThreshold = 120; [Description("#.#.#. = Red/Blue/Green - RGB Colors for the Admin Chat Color. Max value: 255")] public float[] SuperAdminChatRGB = { 255, 0, 0 }; [Description("The Chat Prefix before an admin speaks. eg. *The prefix was set to \"(Admin) \", so.. (Admin) : Hi! Note: If you put a space after the prefix, it will look like this: (Admin) !permissions.Contains(s))); @@ -167,7 +167,7 @@ namespace TShockAPI.DB if (!GroupExists(name)) return "Error: Group doesn't exists."; - var group = Tools.GetGroup(name); + var group = TShock.Utils.GetGroup(name); //Only get permissions that exist in the group. var newperms = group.permissions.Except( permissions ); diff --git a/TShockAPI/DB/InventoryManager.cs b/TShockAPI/DB/InventoryManager.cs new file mode 100644 index 00000000..0ea940f2 --- /dev/null +++ b/TShockAPI/DB/InventoryManager.cs @@ -0,0 +1,102 @@ +/* +TShock, a server mod for Terraria +Copyright (C) 2011 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.Data; + +using MySql.Data.MySqlClient; +using Terraria; + +namespace TShockAPI.DB +{ + public class InventoryManager + { + public IDbConnection database; + + public InventoryManager(IDbConnection db) + { + database = db; + + var table = new SqlTable("Inventory", + new SqlColumn("Account", MySqlDbType.Int32) { Primary = true }, + new SqlColumn("MaxHealth", MySqlDbType.Int32), + new SqlColumn("MaxMana", MySqlDbType.Int32), + new SqlColumn("Inventory", MySqlDbType.Text) + ); + var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator()); + creator.EnsureExists(table); + } + + public PlayerData GetPlayerData(TSPlayer player, int acctid) + { + PlayerData playerData = new PlayerData(player); + + try + { + using (var reader = database.QueryReader("SELECT * FROM Inventory WHERE Account=@0", acctid)) + { + if (reader.Read()) + { + playerData.exists = true; + playerData.maxHealth = reader.Get("MaxHealth"); + playerData.maxMana = reader.Get("MaxMana"); + playerData.inventory = NetItem.Parse(reader.Get("Inventory")); + return playerData; + } + } + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + + return playerData; + } + + public bool InsertPlayerData(TSPlayer player, int acctid) + { + PlayerData playerData = player.PlayerData; + + if (!GetPlayerData(player, acctid).exists) + { + try + { + database.Query("INSERT INTO Inventory (Account, MaxHealth, MaxMana, Inventory) VALUES (@0, @1, @2, @3);", acctid, playerData.maxHealth, playerData.maxMana, NetItem.ToString(playerData.inventory)); + return true; + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + } + else + { + try + { + database.Query("UPDATE Inventory SET MaxHealth = @0, MaxMana = @1, Inventory = @2 WHERE Account = @3;", playerData.maxHealth, playerData.maxMana, NetItem.ToString(playerData.inventory), acctid); + return true; + } + catch (Exception ex) + { + Log.Error(ex.ToString()); + } + } + return false; + } + } +} diff --git a/TShockAPI/DB/ItemManager.cs b/TShockAPI/DB/ItemManager.cs index d44db632..d0beb4ab 100644 --- a/TShockAPI/DB/ItemManager.cs +++ b/TShockAPI/DB/ItemManager.cs @@ -39,7 +39,7 @@ namespace TShockAPI.DB int id = 0; int.TryParse(line, out id); - database.Query(query, Tools.GetItemById(id).name); + database.Query(query, TShock.Utils.GetItemById(id).name); } } } @@ -70,7 +70,7 @@ namespace TShockAPI.DB { try { - database.Query("INSERT INTO ItemBans (ItemName) VALUES (@0);", Tools.GetItemByName(itemname)[0].name); + database.Query("INSERT INTO ItemBans (ItemName) VALUES (@0);", TShock.Utils.GetItemByName(itemname)[0].name); if (!ItemIsBanned(itemname)) ItemBans.Add(itemname); } @@ -86,7 +86,7 @@ namespace TShockAPI.DB return; try { - database.Query("Delete FROM 'ItemBans' WHERE ItemName=@0;", Tools.GetItemByName(itemname)[0].name); + database.Query("Delete FROM 'ItemBans' WHERE ItemName=@0;", TShock.Utils.GetItemByName(itemname)[0].name); ItemBans.Remove(itemname); } catch (Exception ex) diff --git a/TShockAPI/DB/UserManager.cs b/TShockAPI/DB/UserManager.cs index 9cfb092f..91b1dd93 100644 --- a/TShockAPI/DB/UserManager.cs +++ b/TShockAPI/DB/UserManager.cs @@ -102,7 +102,7 @@ namespace TShockAPI.DB if (!TShock.Groups.GroupExists(user.Group)) throw new GroupNotExistsException(user.Group); - if (database.Query("INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@0, @1, @2, @3);", user.Name, Tools.HashPassword(user.Password), user.Group, user.Address) < 1) + if (database.Query("INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@0, @1, @2, @3);", user.Name, TShock.Utils.HashPassword(user.Password), user.Group, user.Address) < 1) throw new UserExistsException(user.Name); } catch (Exception ex) @@ -148,7 +148,7 @@ namespace TShockAPI.DB { try { - if (database.Query("UPDATE Users SET Password = @0 WHERE Username = @1;", Tools.HashPassword(password), user.Name) == 0) + if (database.Query("UPDATE Users SET Password = @0 WHERE Username = @1;", TShock.Utils.HashPassword(password), user.Name) == 0) throw new UserNotExistException(user.Name); } catch (Exception ex) @@ -210,7 +210,7 @@ namespace TShockAPI.DB if (reader.Read()) { string group = reader.Get("UserGroup"); - return Tools.GetGroup(group); + return TShock.Utils.GetGroup(group); } } } @@ -218,7 +218,7 @@ namespace TShockAPI.DB { Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex); } - return Tools.GetGroup("default"); + return TShock.Utils.GetGroup("default"); } public Group GetGroupForIPExpensive(string ip) @@ -229,9 +229,9 @@ namespace TShockAPI.DB { while (reader.Read()) { - if (Tools.GetIPv4Address(reader.Get("IP")) == ip) + if (TShock.Utils.GetIPv4Address(reader.Get("IP")) == ip) { - return Tools.GetGroup(reader.Get("UserGroup")); + return TShock.Utils.GetGroup(reader.Get("UserGroup")); } } } @@ -240,7 +240,7 @@ namespace TShockAPI.DB { Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex); } - return Tools.GetGroup("default"); + return TShock.Utils.GetGroup("default"); } diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs index 282eda95..4d5f6b8e 100644 --- a/TShockAPI/FileTools.cs +++ b/TShockAPI/FileTools.cs @@ -91,7 +91,7 @@ namespace TShockAPI using (var tr = new StreamReader(WhitelistPath)) { string whitelist = tr.ReadToEnd(); - ip = Tools.GetRealIP(ip); + ip = TShock.Utils.GetRealIP(ip); bool contains = whitelist.Contains(ip); if (!contains) { @@ -99,7 +99,7 @@ namespace TShockAPI { if (string.IsNullOrWhiteSpace(line)) continue; - contains = Tools.GetIPv4Address(line).Equals(ip); + contains = TShock.Utils.GetIPv4Address(line).Equals(ip); if (contains) return true; } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 62d0fcb1..a7423bb5 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -25,6 +25,7 @@ using Terraria; using TShockAPI.Net; using System.IO.Streams; +using System.Net; namespace TShockAPI { @@ -48,62 +49,26 @@ namespace TShockAPI public static class GetDataHandlers { private static Dictionary GetDataHandlerDelegates; - public static bool[] BlacklistTiles; + public static int[] WhitelistBuffMaxTime; public static void InitGetDataHandler() { - #region Blacklisted tiles + #region Blacklists - BlacklistTiles = new bool[Main.maxTileSets]; - BlacklistTiles[0] = true; - BlacklistTiles[1] = true; - BlacklistTiles[2] = true; - BlacklistTiles[6] = true; - BlacklistTiles[7] = true; - BlacklistTiles[8] = true; - BlacklistTiles[9] = true; - BlacklistTiles[22] = true; - BlacklistTiles[23] = true; - BlacklistTiles[25] = true; - BlacklistTiles[30] = true; - BlacklistTiles[37] = true; - BlacklistTiles[38] = true; - BlacklistTiles[39] = true; - BlacklistTiles[40] = true; - BlacklistTiles[41] = true; - BlacklistTiles[43] = true; - BlacklistTiles[44] = true; - BlacklistTiles[45] = true; - BlacklistTiles[46] = true; - BlacklistTiles[47] = true; - BlacklistTiles[53] = true; - BlacklistTiles[54] = true; - BlacklistTiles[56] = true; - BlacklistTiles[57] = true; - BlacklistTiles[58] = true; - BlacklistTiles[59] = true; - BlacklistTiles[60] = true; - BlacklistTiles[63] = true; - BlacklistTiles[64] = true; - BlacklistTiles[65] = true; - BlacklistTiles[66] = true; - BlacklistTiles[67] = true; - BlacklistTiles[68] = true; - BlacklistTiles[70] = true; - BlacklistTiles[75] = true; - BlacklistTiles[76] = true; + WhitelistBuffMaxTime = new int[Main.maxBuffs]; + WhitelistBuffMaxTime[20] = 600; + WhitelistBuffMaxTime[0x18] = 1200; + WhitelistBuffMaxTime[0x1f] = 120; + WhitelistBuffMaxTime[0x27] = 420; - #endregion Blacklisted tiles + #endregion Blacklists GetDataHandlerDelegates = new Dictionary { {PacketTypes.PlayerInfo, HandlePlayerInfo}, - {PacketTypes.TileSendSection, HandleSendSection}, {PacketTypes.PlayerUpdate, HandlePlayerUpdate}, {PacketTypes.Tile, HandleTile}, {PacketTypes.TileSendSquare, HandleSendTileSquare}, - {PacketTypes.NpcUpdate, HandleNpcUpdate}, - {PacketTypes.PlayerDamage, HandlePlayerDamage}, {PacketTypes.ProjectileNew, HandleProjectileNew}, {PacketTypes.TogglePvp, HandleTogglePvp}, {PacketTypes.TileKill, HandleTileKill}, @@ -111,10 +76,20 @@ namespace TShockAPI {PacketTypes.LiquidSet, HandleLiquidSet}, {PacketTypes.PlayerSpawn, HandleSpawn}, {PacketTypes.SyncPlayers, HandleSync}, - {PacketTypes.ChestGetContents, HandleChest}, + {PacketTypes.ChestGetContents, HandleChestOpen}, + {PacketTypes.ChestItem, HandleChestItem}, {PacketTypes.SignNew, HandleSign}, {PacketTypes.PlayerSlot, HandlePlayerSlot}, {PacketTypes.TileGetSection, HandleGetSection}, + {PacketTypes.UpdateNPCHome, UpdateNPCHome}, + {PacketTypes.PlayerAddBuff, HandlePlayerBuff}, + {PacketTypes.ItemDrop, HandleItemDrop}, + {PacketTypes.PlayerHp, HandlePlayerHp}, + {PacketTypes.PlayerMana, HandlePlayerMana}, + {PacketTypes.PlayerDamage, HandlePlayerDamage}, + {PacketTypes.NpcStrike, HandleNpcStrike}, + {PacketTypes.NpcSpecial, HandleSpecial}, + {PacketTypes.PlayerAnimation, HandlePlayerAnimation}, }; } @@ -145,20 +120,69 @@ namespace TShockAPI int plr = args.Data.ReadInt8(); int slot = args.Data.ReadInt8(); int stack = args.Data.ReadInt8(); - int namelength = (int)(args.Data.Length - args.Data.Position - 1); + short prefix = (short) args.Data.ReadInt8(); + int type = (int) args.Data.ReadInt16(); - if (namelength > 0) + if (plr != args.Player.Index) { - string itemname = Encoding.ASCII.GetString(args.Data.ReadBytes(namelength)); + return true; + } - if (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned(itemname)) - args.Player.Disconnect("Using banned item: " + itemname + ", remove it and rejoin"); - if (itemname == "KANNIBALE BLADE" - || itemname == "Super Gel") - return Tools.HandleCheater(args.Player, string.Format(TShock.Config.GriefClientReason, "KANNIBALE")); - if (Tools.GetItemByName(itemname).Count == 0 && !args.Player.Group.HasPermission(Permissions.ignorecheatdetection) - && TShock.Config.KickCustomItems) - args.Player.Disconnect("Using custom item: " + itemname + ", remove it and region"); + if (slot < 0 || slot > NetItem.maxNetInventory) + { + return true; + } + + var item = new Item(); + item.netDefaults(type); + item.Prefix(prefix); + + if (stack > item.maxStack && type != 0) + { + args.Player.IgnoreActionsForCheating = true; + } + + if (args.Player.IsLoggedIn) + { + args.Player.PlayerData.StoreSlot(slot, type, prefix, stack); + } + + return false; + } + + private static bool HandlePlayerHp(GetDataHandlerArgs args) + { + int plr = args.Data.ReadInt8(); + int cur = args.Data.ReadInt16(); + int max = args.Data.ReadInt16(); + + if (cur > 600 || max > 600) + { + args.Player.IgnoreActionsForCheating = true; + } + + if (args.Player.IsLoggedIn) + { + args.Player.PlayerData.maxHealth = max; + } + + return false; + } + + private static bool HandlePlayerMana(GetDataHandlerArgs args) + { + int plr = args.Data.ReadInt8(); + int cur = args.Data.ReadInt16(); + int max = args.Data.ReadInt16(); + + if (cur > 600 || max > 600) + { + args.Player.IgnoreActionsForCheating = true; + } + + if (args.Player.IsLoggedIn) + { + args.Player.PlayerData.maxMana = max; } return false; @@ -166,67 +190,98 @@ namespace TShockAPI private static bool HandlePlayerInfo(GetDataHandlerArgs args) { - byte playerid = args.Data.ReadInt8(); - byte hair = args.Data.ReadInt8(); - byte male = args.Data.ReadInt8(); + var playerid = args.Data.ReadInt8(); + var hair = args.Data.ReadInt8(); + var male = args.Data.ReadInt8(); args.Data.Position += 21; - byte difficulty = args.Data.ReadInt8(); + var difficulty = args.Data.ReadInt8(); string name = Encoding.ASCII.GetString(args.Data.ReadBytes((int)(args.Data.Length - args.Data.Position - 1))); - if (hair >= Main.maxHair) + if (!TShock.Utils.ValidString(name)) { - Tools.ForceKick(args.Player, "Hair crash exploit."); - return true; - } - if (!Tools.ValidString(name)) - { - Tools.ForceKick(args.Player, "Unprintable character in name"); + TShock.Utils.ForceKick(args.Player, "Unprintable character in name"); return true; } if (name.Length > 32) { - Tools.ForceKick(args.Player, "Name exceeded 32 characters."); + TShock.Utils.ForceKick(args.Player, "Name exceeded 32 characters."); return true; } if (name.Trim().Length == 0) { - Tools.ForceKick(args.Player, "Empty Name."); + TShock.Utils.ForceKick(args.Player, "Empty Name."); return true; } var ban = TShock.Bans.GetBanByName(name); if (ban != null) { - Tools.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason)); + TShock.Utils.ForceKick(args.Player, string.Format("You are banned: {0}", ban.Reason)); return true; } if (args.Player.ReceivedInfo) { - return Tools.HandleGriefer(args.Player, "Sent client info more than once"); + return true; } if (TShock.Config.MediumcoreOnly && difficulty < 1) { - Tools.ForceKick(args.Player, "Server is set to mediumcore and above characters only!"); + TShock.Utils.ForceKick(args.Player, "Server is set to mediumcore and above characters only!"); return true; } if (TShock.Config.HardcoreOnly && difficulty < 2) { - Tools.ForceKick(args.Player, "Server is set to hardcore characters only!"); + TShock.Utils.ForceKick(args.Player, "Server is set to hardcore characters only!"); return true; } args.Player.Difficulty = difficulty; + args.TPlayer.name = name; args.Player.ReceivedInfo = true; + + NetMessage.SendData((int)PacketTypes.TimeSet, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY); + + if (TShock.Config.EnableGeoIP && TShock.Geo != null) + { + var code = TShock.Geo.TryGetCountryCode(IPAddress.Parse(args.Player.IP)); + args.Player.Country = code == null ? "N/A" : MaxMind.GeoIPCountry.GetCountryNameByCode(code); + if (code == "A1") + if (TShock.Config.KickProxyUsers) + TShock.Utils.Kick(args.Player, "Proxies are not allowed"); + Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined.", args.Player.Name, args.Player.IP, args.Player.Group.Name, args.Player.Country)); + TShock.Utils.Broadcast(args.Player.Name + " has joined from the " + args.Player.Country, Color.Yellow); + } + else + { + Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", args.Player.Name, args.Player.IP, args.Player.Group.Name)); + TShock.Utils.Broadcast(args.Player.Name + " has joined", Color.Yellow); + } + + if (TShock.Config.DisplayIPToAdmins) + TShock.Utils.SendLogs(string.Format("{0} has joined. IP: {1}", args.Player.Name, args.Player.IP), Color.Blue); + return false; } private static bool HandleSendTileSquare(GetDataHandlerArgs args) { - short size = args.Data.ReadInt16(); - int tilex = args.Data.ReadInt32(); - int tiley = args.Data.ReadInt32(); + + var size = args.Data.ReadInt16(); + var tileX = args.Data.ReadInt32(); + var tileY = args.Data.ReadInt32(); if (size > 5) return true; + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendTileSquare(tileX, tileY, size); + return true; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + var tiles = new NetTile[size, size]; for (int x = 0; x < size; x++) @@ -240,20 +295,31 @@ namespace TShockAPI bool changed = false; for (int x = 0; x < size; x++) { - int realx = tilex + x; + int realx = tileX + x; if (realx < 0 || realx >= Main.maxTilesX) continue; for (int y = 0; y < size; y++) { - int realy = tiley + y; - if (realy < 0 || realy >= Main.maxTilesY) + int realy = tileY + y; + if (realy < 0 || realy >= Main.maxTilesY) + continue; + + var tile = Main.tile[realx, realy]; + var newtile = tiles[x, y]; + if(TShock.CheckTilePermission(args.Player, x, y)) + { continue; + } + if ((tile.type == 128 && newtile.Type == 128) || (tile.type == 105 && newtile.Type == 105)) + { + if (TShock.Config.EnableInsecureTileFixes) + { + return false; + } + } - var tile = Main.tile[realx, realy]; - var newtile = tiles[x, y]; - - if (tile.type == 0x17 && newtile.Type == 0x2) + if (tile.type == 0x17 && newtile.Type == 0x2) { tile.type = 0x2; changed = true; @@ -270,147 +336,188 @@ namespace TShockAPI tile.frameY = newtile.FrameY; changed = true; } + // Holy water/Unholy water + else if (tile.type == 1 && newtile.Type == 117) + { + tile.type = 117; + changed = true; + } + else if (tile.type == 1 && newtile.Type == 25) + { + tile.type = 25; + changed = true; + } + else if (tile.type == 117 && newtile.Type == 25) + { + tile.type = 25; + changed = true; + } + else if (tile.type == 25 && newtile.Type == 117) + { + tile.type = 117; + changed = true; + } + else if (tile.type == 2 && newtile.Type == 23) + { + tile.type = 23; + changed = true; + } + else if (tile.type == 2 && newtile.Type == 109) + { + tile.type = 109; + changed = true; + } + else if (tile.type == 23 && newtile.Type == 109) + { + tile.type = 109; + changed = true; + } + else if (tile.type == 109 && newtile.Type == 23) + { + tile.type = 23; + changed = true; + } + else if (tile.type == 23 && newtile.Type == 109) + { + tile.type = 109; + changed = true; + } + else if (tile.type == 53 && newtile.Type == 116) + { + tile.type = 116; + changed = true; + } + else if (tile.type == 53 && newtile.Type == 112) + { + tile.type = 112; + changed = true; + } + else if (tile.type == 112 && newtile.Type == 116) + { + tile.type = 116; + changed = true; + } + else if (tile.type == 116 && newtile.Type == 112) + { + tile.type = 112; + changed = true; + } + else if (tile.type == 112 && newtile.Type == 53) + { + tile.type = 53; + changed = true; + } + else if (tile.type == 109 && newtile.Type == 2) + { + tile.type = 2; + changed = true; + } + else if (tile.type == 116 && newtile.Type == 53) + { + tile.type = 53; + changed = true; + } + else if (tile.type == 117 && newtile.Type == 1) + { + tile.type = 1; + changed = true; + } } } - if (changed) - TSPlayer.All.SendTileSquare(tilex, tiley, 3); - - return true; + if (changed) + { + TSPlayer.All.SendTileSquare(tileX, tileY, size); + WorldGen.RangeFrame(tileX, tileY, tileX + size, tileY + size); + } + return true; } private static bool HandleTile(GetDataHandlerArgs args) { - byte type = args.Data.ReadInt8(); - int x = args.Data.ReadInt32(); - int y = args.Data.ReadInt32(); - byte tiletype = args.Data.ReadInt8(); + var type = args.Data.ReadInt8(); + var tileX = args.Data.ReadInt32(); + var tileY = args.Data.ReadInt32(); + var tiletype = args.Data.ReadInt8(); + + if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY) + return false; if (args.Player.AwaitingName) { - if (TShock.Regions.InAreaRegionName(x, y) == null) + if (TShock.Regions.InAreaRegionName(tileX, tileY) == null) { args.Player.SendMessage("Region is not protected", Color.Yellow); } else { - args.Player.SendMessage("Region Name: " + TShock.Regions.InAreaRegionName(x, y), Color.Yellow); + args.Player.SendMessage("Region Name: " + TShock.Regions.InAreaRegionName(tileX, tileY), Color.Yellow); } - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); args.Player.AwaitingName = false; return true; } if (args.Player.AwaitingTempPoint > 0) { - args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].X = x; - args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].Y = y; + args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].X = tileX; + args.Player.TempPoints[args.Player.AwaitingTempPoint - 1].Y = tileY; args.Player.SendMessage("Set Temp Point " + args.Player.AwaitingTempPoint, Color.Yellow); - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); args.Player.AwaitingTempPoint = 0; return true; } - if (!args.Player.Group.HasPermission(Permissions.canbuild)) - { - if (!args.Player.HasBeenSpammedWithBuildMessage) - { - args.Player.SendMessage("You do not have permission to build!", Color.Red); - args.Player.HasBeenSpammedWithBuildMessage = true; - } - args.Player.SendTileSquare(x, y); - return true; - } if (type == 1 || type == 3) { - int plyX = Math.Abs(args.Player.TileX); - int plyY = Math.Abs(args.Player.TileY); - int tileX = Math.Abs(x); - int tileY = Math.Abs(y); - if (tiletype >= ((type == 1) ? Main.maxTileSets : Main.maxWallTypes)) { - Tools.HandleGriefer(args.Player, string.Format(TShock.Config.TileAbuseReason, "Invalid tile type")); return true; } - if (TShock.Config.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32))) + if (tiletype == 48 && !args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Spikes")) { - if (!(type == 1 && ((tiletype == 0 && args.Player.TPlayer.selectedItem == 114) || (tiletype == 53 && args.Player.TPlayer.selectedItem == 266)))) - { - Log.Debug(string.Format("TilePlaced(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Type:{6})", - plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), tiletype)); - return Tools.HandleGriefer(args.Player, TShock.Config.RangeCheckBanReason); - } - } - if (tiletype == 48 && !args.Player.Group.HasPermission(Permissions.canspike)) - { - args.Player.SendMessage("You do not have permission to place spikes.", Color.Red); - Tools.SendLogs(string.Format("{0} tried to place spikes", args.Player.Name), Color.Red); - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); return true; } - if (type == 1 && tiletype == 21 && Tools.MaxChests()) + if (type == 1 && tiletype == 21 && TShock.Utils.MaxChests()) { args.Player.SendMessage("Reached world's max chest limit, unable to place more!", Color.Red); - Log.Info("Reached world's chest limit, unable to place more."); - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); return true; } - } - if (!args.Player.Group.HasPermission(Permissions.editspawn) && !TShock.Regions.CanBuild(x, y, args.Player) && TShock.Regions.InArea(x, y)) - { - if ((DateTime.UtcNow - args.Player.LastTileChangeNotify).TotalMilliseconds > 1000) + if (tiletype == 141 && !args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Explosives")) { - args.Player.SendMessage("Region Name: " + TShock.Regions.InAreaRegionName(x, y) + " protected from changes.", Color.Red); - args.Player.LastTileChangeNotify = DateTime.UtcNow; - } - args.Player.SendTileSquare(x, y); - return true; - } - if (TShock.Config.DisableBuild) - { - if (!args.Player.Group.HasPermission(Permissions.editspawn)) - { - if ((DateTime.UtcNow - args.Player.LastTileChangeNotify).TotalMilliseconds > 1000) - { - args.Player.SendMessage("World protected from changes.", Color.Red); - args.Player.LastTileChangeNotify = DateTime.UtcNow; - } - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); return true; } } - if (TShock.Config.SpawnProtection) - { - if (!args.Player.Group.HasPermission(Permissions.editspawn)) - { - var flag = TShock.CheckSpawn(x, y); - if (flag) - { - if ((DateTime.UtcNow - args.Player.LastTileChangeNotify).TotalMilliseconds > 1000) - { - args.Player.SendMessage("Spawn protected from changes.", Color.Red); - args.Player.LastTileChangeNotify = DateTime.UtcNow; - } - args.Player.SendTileSquare(x, y); - return true; - } - } - } - if (type == 0 && BlacklistTiles[Main.tile[x, y].type] && args.Player.Active) - { - args.Player.TileThreshold++; - var coords = new Vector2(x, y); - if (!args.Player.TilesDestroyed.ContainsKey(coords)) - args.Player.TilesDestroyed.Add(coords, Main.tile[x, y].Data); - } - if ((DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds < 1000) + if (TShock.CheckIgnores(args.Player)) { - args.Player.SendMessage("Please wait another " + (1000 - (DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds) + " milliseconds before placing/destroying tiles", Color.Red); - args.Player.SendTileSquare(x, y); + args.Player.SendTileSquare(tileX, tileY); return true; } + + if (TShock.CheckTilePermission(args.Player, tileX, tileY)) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + + if (type == 0 && Main.tileSolid[Main.tile[tileX, tileY].type] && args.Player.Active) + { + args.Player.TileThreshold++; + var coords = new Vector2(tileX, tileY); + if (!args.Player.TilesDestroyed.ContainsKey(coords)) + args.Player.TilesDestroyed.Add(coords, Main.tile[tileX, tileY]); + } + + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + return false; } @@ -419,129 +526,204 @@ namespace TShockAPI int id = args.Data.ReadByte(); bool pvp = args.Data.ReadBoolean(); - long seconds = (long)(DateTime.UtcNow - args.Player.LastPvpChange).TotalSeconds; - if (TShock.Config.PvpThrottle > 0 && seconds < TShock.Config.PvpThrottle) + if (id != args.Player.Index) { - args.Player.SendMessage(string.Format("You cannot change pvp status for {0} seconds", TShock.Config.PvpThrottle - seconds), 255, 0, 0); - args.Player.SetPvP(id != args.Player.Index || TShock.Config.AlwaysPvP ? true : args.TPlayer.hostile); + return true; } - else + + if (args.TPlayer.hostile != pvp) { - args.Player.SetPvP(id != args.Player.Index || TShock.Config.AlwaysPvP ? true : pvp); + long seconds = (long)(DateTime.UtcNow - args.Player.LastPvpChange).TotalSeconds; + if (seconds > 5) + { + TSPlayer.All.SendMessage(string.Format("{0} has {1} PvP!", args.Player.Name, pvp ? "enabled" : "disabled"), Main.teamColor[args.Player.Team]); + } + args.Player.LastPvpChange = DateTime.UtcNow; } + + args.TPlayer.hostile = pvp; + + if (TShock.Config.AlwaysPvP) + { + if (pvp == true) + args.Player.IgnoreActionsForPvP = false; + else + { + args.Player.Spawn(); + args.Player.IgnoreActionsForPvP = true; + } + } + + NetMessage.SendData((int)PacketTypes.TogglePvp, -1, -1, "", args.Player.Index); + return true; } - private static bool HandleSendSection(GetDataHandlerArgs args) - { - return Tools.HandleGriefer(args.Player, TShock.Config.SendSectionAbuseReason); - } - - private static bool HandleNpcUpdate(GetDataHandlerArgs args) - { - return Tools.HandleGriefer(args.Player, TShock.Config.NPCSpawnAbuseReason); - } - private static bool HandlePlayerUpdate(GetDataHandlerArgs args) { - byte plr = args.Data.ReadInt8(); - byte control = args.Data.ReadInt8(); - byte item = args.Data.ReadInt8(); - float posx = args.Data.ReadSingle(); - float posy = args.Data.ReadSingle(); - float velx = args.Data.ReadSingle(); - float vely = args.Data.ReadSingle(); - - if (Main.verboseNetplay) - Debug.WriteLine("Update: {{{0},{1}}} {{{2}, {3}}}", (int)posx, (int)posy, (int)velx, (int)vely); - - if (plr != args.Player.Index) - { - return Tools.HandleGriefer(args.Player, TShock.Config.UpdatePlayerAbuseReason); - } + var plr = args.Data.ReadInt8(); + var control = args.Data.ReadInt8(); + var item = args.Data.ReadInt8(); + var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); if (item < 0 || item >= args.TPlayer.inventory.Length) { - Tools.HandleGriefer(args.Player, TShock.Config.UpdatePlayerAbuseReason); return true; } + if ((control & 32) == 32) + { + if (!args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned(args.TPlayer.inventory[item].name)) + { + args.Player.LastThreat = DateTime.UtcNow; + args.Player.SendMessage(string.Format("You cannot use {0} on this server. Your actions are being ignored.", args.TPlayer.inventory[item].name), Color.Red); + return true; + } + } + + if (!pos.Equals(args.Player.LastNetPosition)) + { + float distance = Vector2.Distance(new Vector2((pos.X / 16f), (pos.Y / 16f)), new Vector2(Main.spawnTileX, Main.spawnTileY)); + if (TShock.CheckIgnores(args.Player) && distance > 6f) + { + if (args.Player.IgnoreActionsForCheating) + { + args.Player.SendMessage("You have been disabled for cheating! Please login with a new character!", Color.Red); + } + else if (TShock.Config.ServerSideInventory && !args.Player.IsLoggedIn) + { + args.Player.SendMessage("Server Side Inventory is enabled! Please /register or /login to play!", Color.Red); + } + else if (TShock.Config.AlwaysPvP && !args.TPlayer.hostile) + { + args.Player.SendMessage("PvP is forced! Enable PvP else you can't move or do anything!", Color.Red); + } + args.Player.Spawn(); + return true; + } + } + + args.Player.LastNetPosition = pos; return false; } private static bool HandleProjectileNew(GetDataHandlerArgs args) { - short ident = args.Data.ReadInt16(); - float posx = args.Data.ReadSingle(); - float posy = args.Data.ReadSingle(); - float velx = args.Data.ReadSingle(); - float vely = args.Data.ReadSingle(); - float knockback = args.Data.ReadSingle(); - short dmg = args.Data.ReadInt16(); - byte owner = args.Data.ReadInt8(); - byte type = args.Data.ReadInt8(); + var ident = args.Data.ReadInt16(); + var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + var knockback = args.Data.ReadSingle(); + var dmg = args.Data.ReadInt16(); + var owner = args.Data.ReadInt8(); + var type = args.Data.ReadInt8(); - if (ident > Main.maxProjectiles || ident < 0) + var index = TShock.Utils.SearchProjectile(ident); + + if (index > Main.maxProjectiles || index < 0) { - Tools.HandleGriefer(args.Player, TShock.Config.ExplosiveAbuseReason); return true; } - if (type == 23) + if (args.Player.Index != owner) { - if (velx == 0f && vely == 0f && dmg == 99) - { - Tools.HandleGriefer(args.Player, TShock.Config.ProjectileAbuseReason); - return true; - } - else if (velx == 0f || vely == 0f) - return true; + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; } - - if (type == 29 || type == 28 || type == 37) + if (dmg > 175) { - Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type)); - if (TShock.Config.DisableExplosives && (!args.Player.Group.HasPermission(Permissions.useexplosives) || !args.Player.Group.HasPermission(Permissions.ignoregriefdetection))) - { - Main.projectile[ident].type = 0; - args.Player.SendData(PacketTypes.ProjectileNew, "", ident); - args.Player.SendMessage("Explosives are disabled!", Color.Red); - args.Player.LastExplosive = DateTime.UtcNow; - //return true; - } - else - return Tools.HandleExplosivesUser(args.Player, TShock.Config.ExplosiveAbuseReason); + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; + } + + if (TShock.CheckProjectilePermission(args.Player, index, type)) + { + args.Player.LastThreat = DateTime.UtcNow; + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; + } + + return false; + } + + private static bool HandleProjectileKill(GetDataHandlerArgs args) + { + var ident = args.Data.ReadInt16(); + var owner = args.Data.ReadInt8(); + + if (args.Player.Index != owner) + { + return true; + } + + var index = TShock.Utils.SearchProjectile(ident); + + if (index > Main.maxProjectiles || index < 0) + { + return true; + } + + int type = Main.projectile[index].type; + + if (args.Player.Index != Main.projectile[index].owner) + { + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; + } + + if (TShock.CheckProjectilePermission(args.Player, index, type)) + { + args.Player.LastThreat = DateTime.UtcNow; + args.Player.SendData(PacketTypes.ProjectileNew, "", index); + return true; + } + return false; } private static bool HandlePlayerKillMe(GetDataHandlerArgs args) { - byte id = args.Data.ReadInt8(); - if (id != args.Player.Index) + var id = args.Data.ReadInt8(); + var direction = args.Data.ReadInt8(); + var dmg = args.Data.ReadInt16(); + var pvp = args.Data.ReadInt8() == 0; + + int textlength = (int)(args.Data.Length - args.Data.Position - 1); + string deathtext = ""; + if (textlength > 0) { - return Tools.HandleGriefer(args.Player, TShock.Config.KillMeAbuseReason); + deathtext = Encoding.ASCII.GetString(args.Data.ReadBytes(textlength)); + if (!TShock.Utils.ValidString(deathtext)) + { + return true; + } } + args.Player.LastDeath = DateTime.Now; + if (args.Player.Difficulty != 2) args.Player.ForceSpawn = true; + return false; } - private static bool HandlePlayerDamage(GetDataHandlerArgs args) - { - byte playerid = args.Data.ReadInt8(); - if (TShock.Players[playerid] == null) - return true; - - return !TShock.Players[playerid].TPlayer.hostile; - } - private static bool HandleLiquidSet(GetDataHandlerArgs args) { - int x = args.Data.ReadInt32(); - int y = args.Data.ReadInt32(); + int tileX = args.Data.ReadInt32(); + int tileY = args.Data.ReadInt32(); byte liquid = args.Data.ReadInt8(); bool lava = args.Data.ReadBoolean(); @@ -549,13 +731,23 @@ namespace TShockAPI if (liquid == 0) return false; - int plyX = Math.Abs(args.Player.TileX); - int plyY = Math.Abs(args.Player.TileY); - int tileX = Math.Abs(x); - int tileY = Math.Abs(y); + if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY) + return false; + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } bool bucket = false; - for (int i = 0; i < 44; i++) + for (int i = 0; i < 49; i++) { if (args.TPlayer.inventory[i].type >= 205 && args.TPlayer.inventory[i].type <= 207) { @@ -563,115 +755,66 @@ namespace TShockAPI break; } } - - if (!args.Player.Group.HasPermission(Permissions.canbuild)) - { - args.Player.SendMessage("You do not have permission to build!", Color.Red); - args.Player.SendTileSquare(x, y); - return true; - } - - if (lava && !args.Player.Group.HasPermission(Permissions.canlava)) - { - args.Player.SendMessage("You do not have permission to use lava", Color.Red); - Tools.SendLogs(string.Format("{0} tried using lava", args.Player.Name), Color.Red); - args.Player.SendTileSquare(x, y); - return true; - } - if (!lava && !args.Player.Group.HasPermission(Permissions.canwater)) - { - args.Player.SendMessage("You do not have permission to use water", Color.Red); - Tools.SendLogs(string.Format("{0} tried using water", args.Player.Name), Color.Red); - args.Player.SendTileSquare(x, y); - return true; - } - if (!bucket) { - Log.Debug(string.Format("{0}(PlyXY:{1}_{2}, TileXY:{3}_{4}, Result:{5}_{6}, Amount:{7})", - lava ? "Lava" : "Water", plyX, plyY, tileX, tileY, - Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid)); - return Tools.HandleGriefer(args.Player, TShock.Config.IllogicalLiquidUseReason); ; - } - if (TShock.Config.RangeChecks && ((Math.Abs(plyX - tileX) > 32) || (Math.Abs(plyY - tileY) > 32))) - { - Log.Debug(string.Format("Liquid(PlyXY:{0}_{1}, TileXY:{2}_{3}, Result:{4}_{5}, Amount:{6})", - plyX, plyY, tileX, tileY, Math.Abs(plyX - tileX), Math.Abs(plyY - tileY), liquid)); - return Tools.HandleGriefer(args.Player, TShock.Config.LiquidAbuseReason); + args.Player.SendTileSquare(tileX, tileY); + return true; } - if (TShock.Config.SpawnProtection) + if (lava && !args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Lava Bucket")) { - if (!args.Player.Group.HasPermission(Permissions.editspawn)) - { - var flag = TShock.CheckSpawn(x, y); - if (flag) - { - args.Player.SendMessage("The spawn is protected!", Color.Red); - args.Player.SendTileSquare(x, y); - return true; - } - } + args.Player.SendTileSquare(tileX, tileY); + return true; } + + if (!lava && !args.Player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Water Bucket")) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + if (TShock.CheckTilePermission(args.Player, tileX, tileY)) + { + args.Player.SendTileSquare(tileX, tileY); + return true; + } + return false; } private static bool HandleTileKill(GetDataHandlerArgs args) { - int tilex = args.Data.ReadInt32(); - int tiley = args.Data.ReadInt32(); - if (tilex < 0 || tilex >= Main.maxTilesX || tiley < 0 || tiley >= Main.maxTilesY) + var tileX = args.Data.ReadInt32(); + var tileY = args.Data.ReadInt32(); + + if (tileX < 0 || tileX >= Main.maxTilesX || tileY < 0 || tileY >= Main.maxTilesY) return false; - if (Main.tile[tilex, tiley].type != 0x15 && (!Tools.MaxChests() && Main.tile[tilex, tiley].type != 0)) //Chest + if (TShock.CheckIgnores(args.Player)) { - Log.Debug(string.Format("TileKill(TileXY:{0}_{1}, Type:{2})", - tilex, tiley, Main.tile[tilex, tiley].type)); - Tools.ForceKick(args.Player, string.Format(TShock.Config.TileKillAbuseReason, Main.tile[tilex, tiley].type)); + args.Player.SendTileSquare(tileX, tileY); return true; } - if (!args.Player.Group.HasPermission(Permissions.canbuild)) + + if (Main.tile[tileX, tileY].type != 0x15 && (!TShock.Utils.MaxChests() && Main.tile[tileX, tileY].type != 0)) //Chest { - args.Player.SendMessage("You do not have permission to build!", Color.Red); - args.Player.SendTileSquare(tilex, tiley); + args.Player.SendTileSquare(tileX, tileY); return true; } - if (!args.Player.Group.HasPermission(Permissions.editspawn) && !TShock.Regions.CanBuild(tilex, tiley, args.Player) && TShock.Regions.InArea(tilex, tiley)) + + if (TShock.CheckTilePermission(args.Player, tileX, tileY)) { - args.Player.SendMessage("Region protected from changes.", Color.Red); - args.Player.SendTileSquare(tilex, tiley); + args.Player.SendTileSquare(tileX, tileY); return true; } - if (TShock.Config.DisableBuild) - { - if (!args.Player.Group.HasPermission(Permissions.editspawn)) - { - args.Player.SendMessage("World protected from changes.", Color.Red); - args.Player.SendTileSquare(tilex, tiley); - return true; - } - } - if (TShock.Config.SpawnProtection) - { - if (!args.Player.Group.HasPermission(Permissions.editspawn)) - { - var flag = TShock.CheckSpawn(tilex, tiley); - if (flag) - { - args.Player.SendMessage("Spawn protected from changes.", Color.Red); - args.Player.SendTileSquare(tilex, tiley); - return true; - } - } - } + return false; } private static bool HandleSpawn(GetDataHandlerArgs args) { - byte player = args.Data.ReadInt8(); - int spawnx = args.Data.ReadInt32(); - int spawny = args.Data.ReadInt32(); + var player = args.Data.ReadInt8(); + var spawnx = args.Data.ReadInt32(); + var spawny = args.Data.ReadInt32(); if (args.Player.InitSpawn && args.TPlayer.inventory[args.TPlayer.selectedItem].type != 50) { @@ -681,12 +824,12 @@ namespace TShockAPI { if (TShock.Config.BanOnMediumcoreDeath) { - if (!Tools.Ban(args.Player, TShock.Config.MediumcoreBanReason)) - Tools.ForceKick(args.Player, "Death results in a ban, but can't ban you"); + if (!TShock.Utils.Ban(args.Player, TShock.Config.MediumcoreBanReason)) + TShock.Utils.ForceKick(args.Player, "Death results in a ban, but can't ban you"); } else { - Tools.ForceKick(args.Player, TShock.Config.MediumcoreKickReason); + TShock.Utils.ForceKick(args.Player, TShock.Config.MediumcoreKickReason); } return true; } @@ -698,40 +841,310 @@ namespace TShockAPI return false; } - private static bool HandleChest(GetDataHandlerArgs args) + private static bool HandleChestOpen(GetDataHandlerArgs args) { var x = args.Data.ReadInt32(); var y = args.Data.ReadInt32(); + + if (TShock.CheckIgnores(args.Player)) + { + return true; + } + if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - x) > 32) || (Math.Abs(args.Player.TileY - y) > 32))) { - return Tools.HandleGriefer(args.Player, TShock.Config.RangeCheckBanReason); + return true; } return false; } + private static bool HandleChestItem(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt16(); + var slot = args.Data.ReadInt8(); + var stacks = args.Data.ReadInt8(); + var prefix = args.Data.ReadInt8(); + var type = args.Data.ReadInt16(); + + if (args.TPlayer.chest != id) + { + return false; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.ChestItem, "", id, slot); + return true; + } + + Item item = new Item(); + item.netDefaults(type); + if (stacks > item.maxStack || TShock.Itembans.ItemIsBanned(item.name)) + { + args.Player.SendData(PacketTypes.ChestItem, "", id, slot); + return false; + } + + if (TShock.CheckTilePermission(args.Player, Main.chest[id].x, Main.chest[id].y)) + { + args.Player.SendData(PacketTypes.ChestItem, "", id, slot); + return false; + } + + return false; + } + private static bool HandleSign(GetDataHandlerArgs args) { var id = args.Data.ReadInt16(); var x = args.Data.ReadInt32(); var y = args.Data.ReadInt32(); - if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - x) > 32) || (Math.Abs(args.Player.TileY - y) > 32))) + + if (TShock.CheckTilePermission(args.Player, x, y)) { - return Tools.HandleGriefer(args.Player, TShock.Config.RangeCheckBanReason); + args.Player.SendData(PacketTypes.SignNew, "", id); + return true; } return false; } private static bool HandleGetSection(GetDataHandlerArgs args) { - var x = args.Data.ReadInt32(); - var y = args.Data.ReadInt32(); - if (args.Player.RequestedSection) + return true; + + args.Player.RequestedSection = true; + return false; + } + + private static bool UpdateNPCHome(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt16(); + var x = args.Data.ReadInt16(); + var y = args.Data.ReadInt16(); + var homeless = args.Data.ReadInt8(); + + if (!args.Player.Group.HasPermission(Permissions.movenpc)) { - Tools.ForceKick(args.Player, "Requested sections more than once."); + args.Player.SendMessage("You do not have permission to relocate NPCs.", Color.Red); + args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); return true; } - args.Player.RequestedSection = true; + + if (TShock.CheckTilePermission(args.Player, x, y)) + { + args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); + return true; + } + return false; + } + + private static bool HandlePlayerBuff(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt8(); + var type = args.Data.ReadInt8(); + var time = args.Data.ReadInt16(); + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + return true; + } + if (!TShock.Players[id].TPlayer.hostile) + { + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + return true; + } + if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - TShock.Players[id].TileX) > 64) || (Math.Abs(args.Player.TileY - TShock.Players[id].TileY) > 64))) + { + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + return true; + } + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + return true; + } + + if (WhitelistBuffMaxTime[type] > 0 && time <= WhitelistBuffMaxTime[type]) + { + return false; + } + + args.Player.SendData(PacketTypes.PlayerBuff, "", id); + return true; + } + + private static bool HandleItemDrop(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt16(); + var pos = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + var vel = new Vector2(args.Data.ReadSingle(), args.Data.ReadSingle()); + var stacks = args.Data.ReadInt8(); + var prefix = args.Data.ReadInt8(); + var type = args.Data.ReadInt16(); + + if (type == 0) //Item removed, let client do this to prevent item duplication client side + { + return false; + } + + if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - (pos.X / 16f)) > 64) || (Math.Abs(args.Player.TileY - (pos.Y / 16f)) > 64))) + { + args.Player.SendData(PacketTypes.ItemDrop, "", id); + return true; + } + + Item item = new Item(); + item.netDefaults(type); + if (stacks > item.maxStack || TShock.Itembans.ItemIsBanned(item.name)) + { + args.Player.SendData(PacketTypes.ItemDrop, "", id); + return true; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.ItemDrop, "", id); + return true; + } + + return false; + } + + private static bool HandlePlayerDamage(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt8(); + var direction = args.Data.ReadInt8(); + var dmg = args.Data.ReadInt16(); + var pvp = args.Data.ReadInt8(); + var crit = args.Data.ReadInt8(); + + int textlength = (int)(args.Data.Length - args.Data.Position - 1); + string deathtext = ""; + if (textlength > 0) + { + deathtext = Encoding.ASCII.GetString(args.Data.ReadBytes(textlength)); + if (!TShock.Utils.ValidString(deathtext)) + { + return true; + } + } + + if (TShock.Players[id] == null) + return true; + + if (dmg > 175) + { + args.Player.SendData(PacketTypes.PlayerHp, "", id); + args.Player.SendData(PacketTypes.PlayerUpdate, "", id); + return true; + } + + if (!TShock.Players[id].TPlayer.hostile) + { + args.Player.SendData(PacketTypes.PlayerHp, "", id); + args.Player.SendData(PacketTypes.PlayerUpdate, "", id); + return true; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.PlayerHp, "", id); + args.Player.SendData(PacketTypes.PlayerUpdate, "", id); + return true; + } + + if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - TShock.Players[id].TileX) > 128) || (Math.Abs(args.Player.TileY - TShock.Players[id].TileY) > 128))) + { + args.Player.SendData(PacketTypes.PlayerHp, "", id); + args.Player.SendData(PacketTypes.PlayerUpdate, "", id); + return true; + } + + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendData(PacketTypes.PlayerHp, "", id); + args.Player.SendData(PacketTypes.PlayerUpdate, "", id); + return true; + } + + return false; + } + + private static bool HandleNpcStrike(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt8(); + var direction = args.Data.ReadInt8(); + var dmg = args.Data.ReadInt16(); + var pvp = args.Data.ReadInt8(); + var crit = args.Data.ReadInt8(); + + if (Main.npc[id] == null) + return true; + + if (dmg > 175) + { + args.Player.SendData(PacketTypes.NpcUpdate, "", id); + return true; + } + + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.NpcUpdate, "", id); + return true; + } + + if (Main.npc[id].townNPC && !args.Player.Group.HasPermission(Permissions.movenpc)) + { + args.Player.SendData(PacketTypes.NpcUpdate, "", id); + return true; + } + + if (TShock.Config.RangeChecks && ((Math.Abs(args.Player.TileX - (Main.npc[id].position.X / 16f)) > 128) || (Math.Abs(args.Player.TileY - (Main.npc[id].position.Y / 16f)) > 128))) + { + args.Player.SendData(PacketTypes.NpcUpdate, "", id); + return true; + } + + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendData(PacketTypes.NpcUpdate, "", id); + return true; + } + + return false; + } + + private static bool HandleSpecial(GetDataHandlerArgs args) + { + var id = args.Data.ReadInt8(); + var type = args.Data.ReadInt8(); + + if (type == 1 && TShock.Config.DisableDungeonGuardian) + { + args.Player.SendMessage("The Dungeon Guardian returned you to your spawn point", Color.Purple); + args.Player.Spawn(); + return true; + } + + return false; + } + + private static bool HandlePlayerAnimation(GetDataHandlerArgs args) + { + if (TShock.CheckIgnores(args.Player)) + { + args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index); + return true; + } + + if ((DateTime.UtcNow - args.Player.LastThreat).TotalMilliseconds < 5000) + { + args.Player.SendData(PacketTypes.PlayerAnimation, "", args.Player.Index); + return true; + } + return false; } } diff --git a/TShockAPI/Log.cs b/TShockAPI/Log.cs index 6e158927..3096e765 100644 --- a/TShockAPI/Log.cs +++ b/TShockAPI/Log.cs @@ -131,6 +131,14 @@ namespace TShockAPI Write(message, LogLevel.Debug); } + /// + /// Disposes objects that are being used. + /// + public static void Dispose() + { + _logWriter.Dispose(); + } + /// /// Internal method which writes a message directly to the log file. /// diff --git a/TShockAPI/Net/BaseMsg.cs b/TShockAPI/Net/BaseMsg.cs index 77fa041c..38e9c055 100644 --- a/TShockAPI/Net/BaseMsg.cs +++ b/TShockAPI/Net/BaseMsg.cs @@ -4,8 +4,6 @@ using System.IO.Streams; using System.Linq; using System.Text; -using System.IO.Streams; - namespace TShockAPI.Net { public class BaseMsg : IPackable diff --git a/TShockAPI/Net/NetTile.cs b/TShockAPI/Net/NetTile.cs index 8871065f..73efc484 100644 --- a/TShockAPI/Net/NetTile.cs +++ b/TShockAPI/Net/NetTile.cs @@ -32,6 +32,7 @@ namespace TShockAPI.Net public byte Wall { get; set; } public byte Liquid { get; set; } public bool Lava { get; set; } + public bool Wire { get; set; } public bool HasWall { get { return Wall > 0; } } public bool HasLiquid { get { return Liquid > 0; } } @@ -46,6 +47,7 @@ namespace TShockAPI.Net Wall = 0; Liquid = 0; Lava = false; + Wire = false; } public NetTile(Stream stream) @@ -67,6 +69,8 @@ namespace TShockAPI.Net if (HasLiquid) flags |= TileFlags.Liquid; + if (Wire) + flags |= TileFlags.Wire; stream.WriteInt8((byte)flags); @@ -115,6 +119,9 @@ namespace TShockAPI.Net Liquid = stream.ReadInt8(); Lava = stream.ReadBoolean(); } + + if (flags.HasFlag(TileFlags.Wire)) + Wire = true; } } @@ -126,5 +133,6 @@ namespace TShockAPI.Net Lighted = 2, Wall = 4, Liquid = 8, + Wire = 16 } } diff --git a/TShockAPI/Net/WorldInfoMsg.cs b/TShockAPI/Net/WorldInfoMsg.cs index 8726ced4..d58647c1 100644 --- a/TShockAPI/Net/WorldInfoMsg.cs +++ b/TShockAPI/Net/WorldInfoMsg.cs @@ -32,6 +32,8 @@ namespace TShockAPI.Net DownedBoss1 = 2, DownedBoss2 = 4, DownedBoss3 = 8, + HardMode = 16, + DownedClown = 32 } public class WorldInfoMsg : BaseMsg { diff --git a/TShockAPI/PacketBufferer.cs b/TShockAPI/PacketBufferer.cs index 0257c78f..7c6ffc5e 100644 --- a/TShockAPI/PacketBufferer.cs +++ b/TShockAPI/PacketBufferer.cs @@ -169,7 +169,10 @@ namespace TShockAPI { if (socket.tcpClient.Client != null && socket.tcpClient.Client.Poll(0, SelectMode.SelectWrite)) { - socket.tcpClient.Client.Send(buffer, offset, count, SocketFlags.None); + if (Main.runningMono) + socket.networkStream.Write(buffer, offset, count); + else + socket.tcpClient.Client.Send(buffer, offset, count, SocketFlags.None); return true; } } @@ -179,6 +182,9 @@ namespace TShockAPI catch (SocketException) { } + catch (IOException) + { + } return false; } diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index 60feba1b..b9b620c4 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -23,15 +23,6 @@ namespace TShockAPI [Description("Allows you to use banned items")] public static readonly string usebanneditem; - [Description("Required to be able to place spikes")] - public static readonly string canspike; - - [Description("Required to be able to place/pickup water")] - public static readonly string canwater; - - [Description("Required to be able to place/pickup lava")] - public static readonly string canlava; - [Description("Allows you to edit the spawn")] public static readonly string editspawn; @@ -41,14 +32,8 @@ namespace TShockAPI [Description("Prevents you from being banned")] public static readonly string immunetoban; - [Description("Prevents you from being kicked/banned by TShocks grief detections")] - public static readonly string ignoregriefdetection; - - [Description("Prevents you from being kicked/banned by TShocks cheat detections")] - public static readonly string ignorecheatdetection; - - [Description("Allows you to use explosives even when they are disabled")] - public static readonly string useexplosives; + [Description("Prevents you from being reverted by kill tile abuse detection")] + public static readonly string ignorekilltiledetection; [Description("Specific log messages are sent to users with this permission")] public static readonly string logs; @@ -138,6 +123,24 @@ namespace TShockAPI [Description("")] public static readonly string grow; + [Description("User can change hardmode state.")] + public static readonly string hardmode; + + [Description("User can change the homes of NPCs.")] + public static readonly string movenpc; + + [Description("Users can stop people from TPing to them")] + public static readonly string tpallow; + + [Description("Users can tp to anyone")] + public static readonly string tpall; + + [Description("Users can tp to people without showing a notice")] + public static readonly string tphide; + + [Description("User can convert hallow into corruption and vice-versa")] + public static readonly string converthardmode; + static Permissions() { foreach (var field in typeof(Permissions).GetFields()) diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index 024b84db..7dbf6b6b 100644 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -35,6 +35,5 @@ using System.Runtime.InteropServices; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] - -[assembly: AssemblyVersion("3.3.4.0926")] -[assembly: AssemblyFileVersion("3.3.4.0926")] \ No newline at end of file +[assembly: AssemblyVersion("3.4.0.1221")] +[assembly: AssemblyFileVersion("3.4.0.1221")] diff --git a/TShockAPI/RconHandler.cs b/TShockAPI/RconHandler.cs index d407a144..4d42d8d8 100644 --- a/TShockAPI/RconHandler.cs +++ b/TShockAPI/RconHandler.cs @@ -204,7 +204,7 @@ namespace TShockAPI 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, - Tools.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, + TShock.Utils.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum, Netplay.password != "" ? 1 : 0); if (challenge != "") @@ -223,7 +223,7 @@ namespace TShockAPI 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, - Tools.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, + TShock.Utils.ActivePlayers(), Main.maxNetPlayers - TShock.Config.MaxSlots, TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum, Netplay.password != "" ? 1 : 0) + "\n"; if (challenge != "") @@ -251,7 +251,7 @@ namespace TShockAPI WorldGen.genRand = new Random(); if (text.StartsWith("exit")) { - Tools.ForceKickAll("Server shutting down!"); + TShock.Utils.ForceKickAll("Server shutting down!"); WorldGen.saveWorld(false); Netplay.disconnect = true; return "Server shutting down."; diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index 4c11b64e..cf20d8ef 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -329,7 +329,7 @@ namespace TShockAPI { var returnBlock = new Dictionary(); var playerParam = parameters["player"]; - var found = Tools.FindPlayer(playerParam.ToString()); + var found = TShock.Utils.FindPlayer(playerParam.ToString()); if (found.Count == 0) { returnBlock.Add("status", "400"); @@ -359,7 +359,7 @@ namespace TShockAPI { var returnBlock = new Dictionary(); var playerParam = parameters["player"]; - var found = Tools.FindPlayer(playerParam.ToString()); + var found = TShock.Utils.FindPlayer(playerParam.ToString()); var reason = verbs["reason"]; if (found.Count == 0) { @@ -374,7 +374,7 @@ namespace TShockAPI else if (found.Count == 1) { var player = found[0]; - Tools.ForceKick(player, reason == null ? "Kicked via web" : reason.ToString()); + TShock.Utils.ForceKick(player, reason == null ? "Kicked via web" : reason.ToString()); returnBlock.Add("status", "200"); returnBlock.Add("response", "Player " + player.Name + " was kicked"); } @@ -384,7 +384,7 @@ namespace TShockAPI { var returnBlock = new Dictionary(); var playerParam = parameters["player"]; - var found = Tools.FindPlayer(playerParam.ToString()); + var found = TShock.Utils.FindPlayer(playerParam.ToString()); var reason = verbs["reason"]; if (found.Count == 0) { @@ -400,7 +400,7 @@ namespace TShockAPI { var player = found[0]; TShock.Bans.AddBan(player.IP, player.Name, reason == null ? "Banned via web" : reason.ToString()); - Tools.ForceKick(player, reason == null ? "Banned via web" : reason.ToString()); + TShock.Utils.ForceKick(player, reason == null ? "Banned via web" : reason.ToString()); returnBlock.Add("status", "200"); returnBlock.Add("response", "Player " + player.Name + " was banned"); } diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 9afef6e8..f706badf 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -31,17 +31,17 @@ namespace TShockAPI public static readonly TSServerPlayer Server = new TSServerPlayer(); public static readonly TSPlayer All = new TSPlayer("All"); public int TileThreshold { get; set; } - public Dictionary TilesDestroyed { get; protected set; } + public Dictionary TilesDestroyed { get; protected set; } public bool SyncHP { get; set; } public bool SyncMP { get; set; } public Group Group { get; set; } public bool ReceivedInfo { get; set; } public int Index { get; protected set; } - public DateTime LastPvpChange { get; protected set; } + public DateTime LastPvpChange; public Point[] TempPoints = new Point[2]; public int AwaitingTempPoint { get; set; } public bool AwaitingName { get; set; } - public DateTime LastExplosive { get; set; } + public DateTime LastThreat { get; set; } public DateTime LastTileChangeNotify { get; set; } public bool InitSpawn; public bool DisplayLogs = true; @@ -49,11 +49,13 @@ namespace TShockAPI public TSPlayer LastWhisper; public int LoginAttempts { get; set; } public Vector2 TeleportCoords = new Vector2(-1, -1); + public Vector2 LastNetPosition = Vector2.Zero; public string UserAccountName { get; set; } public bool HasBeenSpammedWithBuildMessage; public bool IsLoggedIn; public int UserID = -1; public bool HasBeenNaggedAboutLoggingIn; + public bool TPAllow = true; public bool TpLock = false; Player FakePlayer; public bool RequestedSection = false; @@ -61,6 +63,11 @@ namespace TShockAPI public bool ForceSpawn = false; public string Country = "??"; public int Difficulty; + private string CacheIP; + public bool IgnoreActionsForPvP = false; + public bool IgnoreActionsForInventory = false; + public bool IgnoreActionsForCheating = false; + public PlayerData PlayerData; public bool RealPlayer { @@ -74,7 +81,10 @@ namespace TShockAPI { get { - return RealPlayer ? Tools.GetRealIP(Netplay.serverSock[Index].tcpClient.Client.RemoteEndPoint.ToString()) : ""; + if (string.IsNullOrEmpty(CacheIP)) + return CacheIP = RealPlayer ? (Netplay.serverSock[Index].tcpClient.Connected ? TShock.Utils.GetRealIP(Netplay.serverSock[Index].tcpClient.Client.RemoteEndPoint.ToString()) : "") : ""; + else + return CacheIP; } } /// @@ -129,9 +139,9 @@ namespace TShockAPI bool flag = false; if (RealPlayer) { - for (int i = 0; i < 40; i++) + for (int i = 0; i < 40; i++) //41 is trash can, 42-45 is coins, 46-49 is ammo { - if (TPlayer.inventory[i] == null || !TPlayer.inventory[i].active) + if (TPlayer.inventory[i] == null || !TPlayer.inventory[i].active || TPlayer.inventory[i].name == "") { flag = true; break; @@ -144,14 +154,14 @@ namespace TShockAPI public TSPlayer(int index) { - TilesDestroyed = new Dictionary(); + TilesDestroyed = new Dictionary(); Index = index; Group = new Group("null"); } protected TSPlayer(String playerName) { - TilesDestroyed = new Dictionary(); + TilesDestroyed = new Dictionary(); Index = -1; FakePlayer = new Player { name = playerName, whoAmi = -1 }; Group = new Group("null"); @@ -194,7 +204,9 @@ namespace TShockAPI WorldFlags = (WorldGen.shadowOrbSmashed ? WorldInfoFlag.OrbSmashed : WorldInfoFlag.None) | (NPC.downedBoss1 ? WorldInfoFlag.DownedBoss1 : WorldInfoFlag.None) | (NPC.downedBoss2 ? WorldInfoFlag.DownedBoss2 : WorldInfoFlag.None) | - (NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None), + (NPC.downedBoss3 ? WorldInfoFlag.DownedBoss3 : WorldInfoFlag.None) | + (Main.hardMode ? WorldInfoFlag.HardMode : WorldInfoFlag.None) | + (NPC.downedClown ? WorldInfoFlag.DownedClown : WorldInfoFlag.None), WorldName = Main.worldName }; msg.PackFull(ms); @@ -212,6 +224,7 @@ namespace TShockAPI //150 Should avoid all client crash errors //The error occurs when a tile trys to update which the client hasnt load yet, Clients only update tiles withen 150 blocks //Try 300 if it does not work (Higher number - Longer load times - Less chance of error) + //Should we properly send sections so that clients don't get tiles twice? if (!SendTileSquare(tilex, tiley)) { InitSpawn = true; @@ -254,7 +267,8 @@ namespace TShockAPI { try { - SendData(PacketTypes.TileSendSquare, "", size, (x - (size / 2)), (y - (size / 2))); + int num = (size - 1) / 2; + SendData(PacketTypes.TileSendSquare, "", size, (float)(x - num), (float)(y - num)); return true; } catch (Exception ex) @@ -264,15 +278,16 @@ namespace TShockAPI return false; } - public virtual void GiveItem(int type, string name, int width, int height, int stack) + 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); + int itemid = Item.NewItem((int)X, (int)Y, width, height, type, stack, true, prefix); // This is for special pickaxe/hammers/swords etc 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].stack = stack; Main.item[itemid].owner = Index; + Main.item[itemid].prefix = (byte) prefix; NetMessage.SendData((int)PacketTypes.ItemDrop, -1, -1, "", itemid, 0f, 0f, 0f); NetMessage.SendData((int)PacketTypes.ItemOwner, -1, -1, "", itemid, 0f, 0f, 0f); } @@ -297,18 +312,6 @@ namespace TShockAPI NetMessage.SendData((int)PacketTypes.PlayerDamage, -1, -1, "", Index, ((new Random()).Next(-1, 1)), damage, (float)0); } - public virtual void SetPvP(bool pvp) - { - if (TPlayer.hostile != pvp) - { - LastPvpChange = DateTime.UtcNow; - TPlayer.hostile = pvp; - All.SendMessage(string.Format("{0} has {1} PvP!", Name, pvp ? "enabled" : "disabled"), Main.teamColor[Team]); - } - //Broadcast anyways to keep players synced - NetMessage.SendData((int)PacketTypes.TogglePvp, -1, -1, "", Index); - } - public virtual void SetTeam(int team) { Main.player[Index].team = team; @@ -374,6 +377,12 @@ namespace TShockAPI Console.WriteLine(msg); RconHandler.Response += msg + "\n"; } + + public void SetFullMoon(bool fullmoon) + { + Main.moonPhase = 0; + SetTime(false, 0); + } public void SetBloodMoon(bool bloodMoon) { @@ -395,7 +404,7 @@ namespace TShockAPI { int spawnTileX; int spawnTileY; - Tools.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX, out spawnTileY); + TShock.Utils.GetRandomClearTileWithInRange(startTileX, startTileY, tileXRange, tileYRange, out spawnTileX, out spawnTileY); int npcid = NPC.NewNPC(spawnTileX * 16, spawnTileY * 16, type, 0); // This is for special slimes Main.npc[npcid].SetDefaults(name); @@ -408,12 +417,12 @@ namespace TShockAPI NetMessage.SendData((int)PacketTypes.NpcStrike, -1, -1, "", npcid, damage, knockBack, hitDirection); } - public void RevertKillTile(Dictionary destroyedTiles) + public void RevertKillTile(Dictionary destroyedTiles) { // Update Main.Tile first so that when tile sqaure is sent it is correct - foreach (KeyValuePair entry in destroyedTiles) + foreach (KeyValuePair entry in destroyedTiles) { - Main.tile[(int)entry.Key.X, (int)entry.Key.Y].Data = entry.Value; + Main.tile[(int)entry.Key.X, (int)entry.Key.Y] = entry.Value; Log.Debug(string.Format("Reverted DestroyedTile(TileXY:{0}_{1}, Type:{2})", entry.Key.X, entry.Key.Y, Main.tile[(int)entry.Key.X, (int)entry.Key.Y].type)); } @@ -424,4 +433,152 @@ namespace TShockAPI } } } + + public class PlayerData + { + public NetItem[] inventory = new NetItem[NetItem.maxNetInventory]; + public int maxHealth = 100; + public int maxMana = 100; + public bool exists = false; + + public PlayerData(TSPlayer player) + { + for (int i = 0; i < NetItem.maxNetInventory; i++) + { + this.inventory[i] = new NetItem(); + } + this.inventory[0].netID = -15; + this.inventory[0].stack = 1; + if(player.TPlayer.inventory[0] != null && player.TPlayer.inventory[0].netID == -15) + this.inventory[0].prefix = player.TPlayer.inventory[0].prefix; + this.inventory[1].netID = -13; + this.inventory[1].stack = 1; + if (player.TPlayer.inventory[1] != null && player.TPlayer.inventory[1].netID == -13) + this.inventory[1].prefix = player.TPlayer.inventory[1].prefix; + this.inventory[2].netID = -16; + this.inventory[2].stack = 1; + if (player.TPlayer.inventory[2] != null && player.TPlayer.inventory[2].netID == -16) + this.inventory[2].prefix = player.TPlayer.inventory[2].prefix; + } + + public void StoreSlot(int slot, int netID, int prefix, int stack) + { + this.inventory[slot].netID = netID; + if (this.inventory[slot].netID != 0) + { + this.inventory[slot].stack = stack; + this.inventory[slot].prefix = prefix; + } + else + { + this.inventory[slot].stack = 0; + this.inventory[slot].prefix = 0; + } + } + + public void CopyInventory(TSPlayer player) + { + this.maxHealth = player.TPlayer.statLifeMax; + this.maxMana = player.TPlayer.statManaMax; + Item[] inventory = player.TPlayer.inventory; + Item[] armor = player.TPlayer.armor; + for (int i = 0; i < NetItem.maxNetInventory; i++) + { + if (i < 49) + { + if (player.TPlayer.inventory[i] != null) + { + this.inventory[i].netID = inventory[i].netID; + } + else + { + this.inventory[i].netID = 0; + } + + if (this.inventory[i].netID != 0) + { + this.inventory[i].stack = inventory[i].stack; + this.inventory[i].prefix = inventory[i].prefix; + } + else + { + this.inventory[i].stack = 0; + this.inventory[i].prefix = 0; + } + } + else + { + if (player.TPlayer.armor[i - 48] != null) + { + this.inventory[i].netID = armor[i - 48].netID; + } + else + { + this.inventory[i].netID = 0; + } + + if (this.inventory[i].netID != 0) + { + this.inventory[i].stack = armor[i - 48].stack; + this.inventory[i].prefix = armor[i - 48].prefix; + } + else + { + this.inventory[i].stack = 0; + this.inventory[i].prefix = 0; + } + } + } + } + } + + public class NetItem + { + public static int maxNetInventory = 59; + public int netID = 0; + public int stack = 0; + public int prefix = 0; + + public static string ToString(NetItem[] inventory) + { + string inventoryString = ""; + for (int i = 0; i < NetItem.maxNetInventory; i++) + { + if (i != 0) + inventoryString += "~"; + inventoryString += inventory[i].netID; + if (inventory[i].netID != 0) + { + inventoryString += "," + inventory[i].stack; + inventoryString += "," + inventory[i].prefix; + } + else + { + inventoryString += ",0,0"; + } + } + return inventoryString; + } + + public static NetItem[] Parse(string data) + { + NetItem[] inventory = new NetItem[NetItem.maxNetInventory]; + int i; + for (i = 0; i < NetItem.maxNetInventory; i++) + { + inventory[i] = new NetItem(); + } + string[] items = data.Split('~'); + i = 0; + foreach (string item in items) + { + string[] idata = item.Split(','); + inventory[i].netID = int.Parse(idata[0]); + inventory[i].stack = int.Parse(idata[1]); + inventory[i].prefix = int.Parse(idata[2]); + i++; + } + return inventory; + } + } } \ No newline at end of file diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index be8a4eb4..c25ea3ed 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -32,10 +32,12 @@ using System.Diagnostics; using System.IO; using System.Net; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using Hooks; using MySql.Data.MySqlClient; +using Newtonsoft.Json; using Rests; using Terraria; using TShockAPI.DB; @@ -43,11 +45,11 @@ using TShockAPI.Net; namespace TShockAPI { - [APIVersion(1, 8)] + [APIVersion(1, 10)] public class TShock : TerrariaPlugin { - public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version; - public static readonly string VersionCodename = "Try the new slim model."; + public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version; + public static readonly string VersionCodename = "Zidonuke fixin' what Redigit doesn't"; public static string SavePath = "tshock"; @@ -60,6 +62,7 @@ namespace TShockAPI public static UserManager Users; public static ItemManager Itembans; public static RemeberedPosManager RememberedPos; + public static InventoryManager InventoryDB; public static ConfigFile Config { get; set; } public static IDbConnection DB; public static bool OverridePort; @@ -67,6 +70,7 @@ namespace TShockAPI public static MaxMind.GeoIPCountry Geo; public static SecureRest RestApi; public static RestManager RestManager; + public static Utils Utils = new Utils(); /// /// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded. @@ -86,7 +90,7 @@ namespace TShockAPI public override string Author { - get { return "The TShock Team"; } + get { return "The Nyx Team"; } } public override string Description @@ -101,9 +105,13 @@ namespace TShockAPI Order = 0; } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] public override void Initialize() { + HandleCommandLine(Environment.GetCommandLineArgs()); + if (!Directory.Exists(SavePath)) Directory.CreateDirectory(SavePath); @@ -114,13 +122,11 @@ namespace TShockAPI #endif AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - try { - if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) { - Log.ConsoleInfo("TShock was improperly shut down. Deleting invalid pid file..."); + Log.ConsoleInfo("TShock was improperly shut down. Please avoid this in the future, world corruption may result from this."); File.Delete(Path.Combine(SavePath, "tshock.pid")); } File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), Process.GetCurrentProcess().Id.ToString()); @@ -128,7 +134,7 @@ namespace TShockAPI ConfigFile.ConfigRead += OnConfigRead; FileTools.SetupConfig(); - HandleCommandLine(Environment.GetCommandLineArgs()); + HandleCommandLine_Port(Environment.GetCommandLineArgs()); if (Config.StorageType.ToLower() == "sqlite") { @@ -172,6 +178,7 @@ namespace TShockAPI Regions = new RegionManager(DB); Itembans = new ItemManager(DB); RememberedPos = new RemeberedPosManager(DB); + InventoryDB = new InventoryManager(DB); RestApi = new SecureRest(Netplay.serverListenIP, 8080); RestApi.Verify += RestApi_Verify; RestApi.Port = Config.RestApiPort; @@ -182,7 +189,7 @@ namespace TShockAPI if (Config.EnableGeoIP && File.Exists(geoippath)) Geo = new MaxMind.GeoIPCountry(geoippath); - Log.ConsoleInfo(string.Format("TShock Version {0} ({1}) now running.", Version, VersionCodename)); + Log.ConsoleInfo(string.Format("TerrariaShock Version {0} ({1}) now running.", Version, VersionCodename)); GameHooks.PostInitialize += OnPostInit; GameHooks.Update += OnUpdate; @@ -194,6 +201,8 @@ namespace TShockAPI NetHooks.SendData += NetHooks_SendData; NetHooks.GreetPlayer += OnGreetPlayer; NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc; + ProjectileHooks.SetDefaults += OnProjectileSetDefaults; + WorldHooks.StartHardMode += OnStartHardMode; GetDataHandlers.InitGetDataHandler(); Commands.InitCommands(); @@ -214,9 +223,54 @@ namespace TShockAPI Log.Error(ex.ToString()); Environment.Exit(1); } + } - RestObject RestApi_Verify(string username, string password) + private void callHome() + { + string fp; + string lolpath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/.tshock/"; + if (!Directory.Exists(lolpath)) + { + Directory.CreateDirectory(lolpath); + } + if (!File.Exists(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint"))) + { + fp = ""; + int random = Utils.Random.Next(500000, 1000000); + fp += random; + + fp = Utils.HashPassword(Netplay.serverIP + fp + Netplay.serverPort + Netplay.serverListenIP); + TextWriter tw = new StreamWriter(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint")); + tw.Write(fp); + tw.Close(); + } else + { + fp = ""; + TextReader tr = new StreamReader(Path.Combine(lolpath, Netplay.serverPort + ".fingerprint")); + fp = tr.ReadToEnd(); + tr.Close(); + } + + using (var client = new WebClient()) + { + client.Headers.Add("user-agent", + "TShock (" + VersionNum + ")"); + try + { + string response = client.DownloadString("http://tshock.co/tickto.php?do=log&fp=" + fp + "&ver=" + VersionNum + "&port=" + Netplay.serverPort); + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("\nRegistered with stat tracker: " + response + "\n"); + Console.ForegroundColor = ConsoleColor.Gray; + } + catch (Exception e) + { + Log.Error(e.ToString()); + } + } + } + + RestObject RestApi_Verify(string username, string password) { var userAccount = TShock.Users.GetUserByName(username); if (userAccount == null) @@ -224,12 +278,12 @@ namespace TShockAPI return new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." }; } - if (Tools.HashPassword(password).ToUpper() != userAccount.Password.ToUpper()) + if (TShock.Utils.HashPassword(password).ToUpper() != userAccount.Password.ToUpper()) { return new RestObject("401") { Error = "Invalid username/password combination provided. Please re-submit your query with a correct pair." }; } - if (!Tools.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin") + if (!TShock.Utils.GetGroup(userAccount.Group).HasPermission("api") && userAccount.Group != "superadmin") { return new RestObject("403") { Error = "Although your account was successfully found and identified, your account lacks the permission required to use the API. (api)" }; } @@ -241,6 +295,7 @@ namespace TShockAPI { if (disposing) { + Geo.Dispose(); GameHooks.PostInitialize -= OnPostInit; GameHooks.Update -= OnUpdate; ServerHooks.Join -= OnJoin; @@ -251,12 +306,13 @@ namespace TShockAPI NetHooks.SendData -= NetHooks_SendData; NetHooks.GreetPlayer -= OnGreetPlayer; NpcHooks.StrikeNpc -= NpcHooks_OnStrikeNpc; + ProjectileHooks.SetDefaults -= OnProjectileSetDefaults; if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) { - Console.WriteLine("Thanks for using TShock! Process ID file is now being destroyed."); File.Delete(Path.Combine(SavePath, "tshock.pid")); } RestApi.Dispose(); + Log.Dispose(); } base.Dispose(disposing); @@ -334,6 +390,13 @@ namespace TShockAPI Log.ConsoleInfo("World path has been set to " + path); } } + } + } + + private void HandleCommandLine_Port(string[] parms) + { + for (int i = 0; i < parms.Length; i++) + { if (parms[i].ToLower() == "-port") { int port = Convert.ToInt32(parms[++i]); @@ -388,6 +451,10 @@ namespace TShockAPI Regions.ReloadAllRegions(); if (Config.RestApiEnabled) RestApi.Start(); + + Thread t = new Thread(callHome); + t.Start(); + } @@ -412,10 +479,7 @@ namespace TShockAPI { if (player.TileThreshold >= Config.TileThreshold) { - if (Tools.HandleTntUser(player, "Kill tile abuse detected.")) - { - TSPlayer.Server.RevertKillTile(player.TilesDestroyed); - } + TSPlayer.Server.RevertKillTile(player.TilesDestroyed); } if (player.TileThreshold > 0) { @@ -447,24 +511,31 @@ namespace TShockAPI player.Group = Users.GetGroupForIP(player.IP); } - if (Tools.ActivePlayers() + 1 > Config.MaxSlots && !player.Group.HasPermission(Permissions.reservedslot)) + if (TShock.Utils.ActivePlayers() + 1 > Config.MaxSlots && !player.Group.HasPermission(Permissions.reservedslot)) { - Tools.ForceKick(player, Config.ServerFullReason); + TShock.Utils.ForceKick(player, Config.ServerFullReason); handler.Handled = true; return; } - var ban = Bans.GetBanByIp(player.IP); + var ipban = Bans.GetBanByIp(player.IP); + var nameban = Bans.GetBanByName(player.Name); + Ban ban = null; + if (ipban != null && Config.EnableIPBans) + ban = ipban; + else if (nameban != null && Config.EnableIPBans) + ban = nameban; + if (ban != null) { - Tools.ForceKick(player, string.Format("You are banned: {0}", ban.Reason)); + TShock.Utils.ForceKick(player, string.Format("You are banned: {0}", ban.Reason)); handler.Handled = true; return; } if (!FileTools.OnWhitelist(player.IP)) { - Tools.ForceKick(player, "Not on whitelist."); + TShock.Utils.ForceKick(player, "Not on whitelist."); handler.Handled = true; return; } @@ -479,8 +550,15 @@ namespace TShockAPI if (tsplr != null && tsplr.ReceivedInfo) { + TShock.Utils.Broadcast(tsplr.Name + " has left", Color.Yellow); Log.Info(string.Format("{0} left.", tsplr.Name)); + if (tsplr.IsLoggedIn) + { + tsplr.PlayerData.CopyInventory(tsplr); + InventoryDB.InsertPlayerData(tsplr, tsplr.UserID); + } + if (Config.RememberLeavePos) { RememberedPos.InsertLeavePos(tsplr.Name, tsplr.IP, (int)(tsplr.X / 16), (int)(tsplr.Y / 16)); @@ -500,22 +578,15 @@ namespace TShockAPI return; } - if (!Tools.ValidString(text)) + if (!TShock.Utils.ValidString(text)) { - Tools.Kick(tsplr, "Unprintable character in chat"); e.Handled = true; return; } - if (msg.whoAmI != ply) - { - e.Handled = Tools.HandleGriefer(tsplr, "Faking Chat"); - return; - } - if (tsplr.Group.HasPermission(Permissions.adminchat) && !text.StartsWith("/") && Config.AdminChatEnabled) { - Tools.Broadcast(Config.AdminChatPrefix + "<" + tsplr.Name + "> " + text, + TShock.Utils.Broadcast(Config.AdminChatPrefix + "<" + tsplr.Name + "> " + text, tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); e.Handled = true; @@ -536,7 +607,7 @@ namespace TShockAPI } else { - Tools.Broadcast("{2}<{0}> {1}".SFormat(tsplr.Name, text, Config.ChatDisplayGroup ? "[{0}] ".SFormat(tsplr.Group.Name) : ""), + TShock.Utils.Broadcast("{2}<{0}> {1}".SFormat(tsplr.Name, text, Config.ChatDisplayGroup ? "[{0}] ".SFormat(tsplr.Group.Name) : ""), tsplr.Group.R, tsplr.Group.G, tsplr.Group.B); //Log.Info(string.Format("{0} said: {1}", tsplr.Name, text)); @@ -566,7 +637,7 @@ namespace TShockAPI if (text.StartsWith("exit")) { - Tools.ForceKickAll("Server shutting down!"); + TShock.Utils.ForceKickAll("Server shutting down!"); } else if (text.StartsWith("playing") || text.StartsWith("/playing")) { @@ -622,13 +693,9 @@ namespace TShockAPI return; } - - // Stop accepting updates from player as this player is going to be kicked/banned during OnUpdate (different thread so can produce race conditions) - if ((Config.BanKillTileAbusers || Config.KickKillTileAbusers) && - player.TileThreshold >= Config.TileThreshold && !player.Group.HasPermission(Permissions.ignoregriefdetection)) + if (player.TileThreshold >= Config.TileThreshold && !player.Group.HasPermission(Permissions.ignorekilltiledetection)) { - Log.Debug("Rejecting " + type + " from " + player.Name + " as this player is about to be kicked"); e.Handled = true; } else @@ -657,30 +724,30 @@ namespace TShockAPI return; } - NetMessage.SendData((int)PacketTypes.TimeSet, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY); - NetMessage.syncPlayers(); - - if (Config.EnableGeoIP && Geo != null) - { - var code = Geo.TryGetCountryCode(IPAddress.Parse(player.IP)); - player.Country = code == null ? "N/A" : MaxMind.GeoIPCountry.GetCountryNameByCode(code); - Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined.", player.Name, player.IP, player.Group.Name, player.Country)); - Tools.Broadcast(player.Name + " is from the " + player.Country, Color.Yellow); - } - else - Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", player.Name, player.IP, player.Group.Name)); - - Tools.ShowFileToUser(player, "motd.txt"); + TShock.Utils.ShowFileToUser(player, "motd.txt"); if (HackedHealth(player)) { - Tools.HandleCheater(player, "Hacked health."); + player.IgnoreActionsForCheating = true; + player.SendMessage("You are using a health/mana cheat. Please choose a different character."); } - if (Config.AlwaysPvP) + + if (HackedInventory(player)) { - player.SetPvP(true); - player.SendMessage( - "PvP is forced! Enable PvP else you can't deal damage to other people. (People can kill you)", - Color.Red); + player.IgnoreActionsForCheating = true; + } + + NetMessage.syncPlayers(); + + if (Config.ServerSideInventory && !player.IsLoggedIn) + { + player.IgnoreActionsForInventory = true; + player.SendMessage("Server Side Inventory is enabled! Please /register or /login to play!", Color.Red); + } + + if (Config.AlwaysPvP && !player.TPlayer.hostile) + { + player.IgnoreActionsForPvP = true; + player.SendMessage("PvP is forced! Enable PvP else you can't move or do anything!", Color.Red); } if (player.Group.HasPermission(Permissions.causeevents) && Config.InfiniteInvasion) { @@ -707,6 +774,13 @@ namespace TShockAPI } } + void OnProjectileSetDefaults(SetDefaultsEventArgs e) + { + if (e.Info == 43) + if (Config.DisableTombstones) + e.Object.SetDefaults(0); + } + /// /// Send bytes to client using packetbuffering if available /// @@ -781,12 +855,18 @@ namespace TShockAPI private void OnSaveWorld(bool resettime, HandledEventArgs e) { - Tools.Broadcast("Saving world. Momentary lag might result from this.", Color.Red); - Thread SaveWorld = new Thread(Tools.SaveWorld); + TShock.Utils.Broadcast("Saving world. Momentary lag might result from this.", Color.Red); + Thread SaveWorld = new Thread(TShock.Utils.SaveWorld); SaveWorld.Start(); e.Handled = true; } + void OnStartHardMode(HandledEventArgs e) + { + if (Config.DisableHardmode) + e.Handled = true; + } + /* * Useful stuff: * */ @@ -800,7 +880,7 @@ namespace TShockAPI } else { - Main.invasionSize = 100 + (Config.InvasionMultiplier * Tools.ActivePlayers()); + Main.invasionSize = 100 + (Config.InvasionMultiplier * TShock.Utils.ActivePlayers()); } Main.invasionWarn = 0; @@ -826,27 +906,99 @@ namespace TShockAPI switch (random) { case 0: - Tools.Broadcast(string.Format("You call that a lot? {0} goblins killed!", KillCount)); + TShock.Utils.Broadcast(string.Format("You call that a lot? {0} goblins killed!", KillCount)); break; case 1: - Tools.Broadcast(string.Format("Fatality! {0} goblins killed!", KillCount)); + TShock.Utils.Broadcast(string.Format("Fatality! {0} goblins killed!", KillCount)); break; case 2: - Tools.Broadcast(string.Format("Number of 'noobs' killed to date: {0}", KillCount)); + TShock.Utils.Broadcast(string.Format("Number of 'noobs' killed to date: {0}", KillCount)); break; case 3: - Tools.Broadcast(string.Format("Duke Nukem would be proud. {0} goblins killed.", KillCount)); + TShock.Utils.Broadcast(string.Format("Duke Nukem would be proud. {0} goblins killed.", KillCount)); break; case 4: - Tools.Broadcast(string.Format("You call that a lot? {0} goblins killed!", KillCount)); + TShock.Utils.Broadcast(string.Format("You call that a lot? {0} goblins killed!", KillCount)); break; case 5: - Tools.Broadcast(string.Format("{0} copies of Call of Duty smashed.", KillCount)); + TShock.Utils.Broadcast(string.Format("{0} copies of Call of Duty smashed.", KillCount)); break; } } } + public static bool CheckProjectilePermission(TSPlayer player, int index, int type) + { + if (type == 43) + { + return true; + } + + if (type == 17 && !player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Dirt Wand")) //Dirt Wand Projectile + { + return true; + } + + if ((type == 42 || type == 65 || type == 68) && !player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned("Sandgun")) //Sandgun Projectiles + { + return true; + } + + Projectile proj = new Projectile(); + proj.SetDefaults(type); + + if (!player.Group.HasPermission(Permissions.usebanneditem) && TShock.Itembans.ItemIsBanned(proj.name)) + { + return true; + } + + if (proj.hostile) + { + return true; + } + + return false; + } + + public static bool CheckTilePermission(TSPlayer player, int tileX, int tileY) + { + if (TShock.Config.RangeChecks && ((Math.Abs(player.TileX - tileX) > 32) || (Math.Abs(player.TileY - tileY) > 32))) + { + return true; + } + if (!player.Group.HasPermission(Permissions.canbuild)) + { + player.SendMessage("You do not have permission to build!", Color.Red); + return true; + } + if (!player.Group.HasPermission(Permissions.editspawn) && !TShock.Regions.CanBuild(tileX, tileY, player) && TShock.Regions.InArea(tileX, tileY)) + { + player.SendMessage("Region protected from changes.", Color.Red); + return true; + } + if (TShock.Config.DisableBuild) + { + if (!player.Group.HasPermission(Permissions.editspawn)) + { + player.SendMessage("World protected from changes.", Color.Red); + return true; + } + } + if (TShock.Config.SpawnProtection) + { + if (!player.Group.HasPermission(Permissions.editspawn)) + { + var flag = TShock.CheckSpawn(tileX, tileY); + if (flag) + { + player.SendMessage("Spawn protected from changes.", Color.Red); + return true; + } + } + } + return false; + } + public static bool CheckSpawn(int x, int y) { Vector2 tile = new Vector2(x, y); @@ -869,6 +1021,151 @@ namespace TShockAPI (player.TPlayer.statLife > 400); } + public static bool HackedInventory(TSPlayer player) + { + bool check = false; + + Item[] inventory = player.TPlayer.inventory; + Item[] armor = player.TPlayer.armor; + for (int i = 0; i < NetItem.maxNetInventory; i++) + { + if (i < 49) + { + Item item = new Item(); + if (inventory[i] != null && inventory[i].netID != 0) + { + item.netDefaults(inventory[i].netID); + item.Prefix(inventory[i].prefix); + item.AffixName(); + if (inventory[i].stack > item.maxStack) + { + check = true; + player.SendMessage(String.Format("Stack cheat detected. Remove item {0} ({1}) and then rejoin", item.name, inventory[i].stack), Color.Cyan); + } + } + } + else + { + Item item = new Item(); + if (armor[i - 48] != null && armor[i - 48].netID != 0) + { + item.netDefaults(armor[i - 48].netID); + item.Prefix(armor[i - 48].prefix); + item.AffixName(); + if (armor[i - 48].stack > item.maxStack) + { + check = true; + player.SendMessage(String.Format("Stack cheat detected. Remove armor {0} ({1}) and then rejoin", item.name, armor[i - 48].stack), Color.Cyan); + } + } + } + } + + return check; + } + + public static bool CheckInventory(TSPlayer player) + { + PlayerData playerData = player.PlayerData; + bool check = true; + + if (player.TPlayer.statLifeMax > playerData.maxHealth) + { + player.SendMessage("Error: Your max health exceeded (" + playerData.maxHealth + ") which is stored on server", Color.Cyan); + check = false; + } + + if (player.TPlayer.statManaMax > playerData.maxMana) + { + player.SendMessage("Error: Your max mana exceeded (" + playerData.maxMana + ") which is stored on server", Color.Cyan); + check = false; + } + + Item[] inventory = player.TPlayer.inventory; + Item[] armor = player.TPlayer.armor; + for (int i = 0; i < NetItem.maxNetInventory; i++) + { + if (i < 49) + { + Item item = new Item(); + Item serverItem = new Item(); + if (inventory[i] != null && inventory[i].netID != 0) + { + if (playerData.inventory[i].netID != inventory[i].netID) + { + item.netDefaults(inventory[i].netID); + item.Prefix(inventory[i].prefix); + item.AffixName(); + player.SendMessage("Error: Your item (" + item.name + ") needs to be deleted.", Color.Cyan); + check = false; + } + else if (playerData.inventory[i].prefix != inventory[i].prefix) + { + item.netDefaults(inventory[i].netID); + item.Prefix(inventory[i].prefix); + item.AffixName(); + player.SendMessage("Error: Your item (" + item.name + ") needs to be deleted.", Color.Cyan); + check = false; + } + else if (inventory[i].stack > playerData.inventory[i].stack) + { + item.netDefaults(inventory[i].netID); + item.Prefix(inventory[i].prefix); + item.AffixName(); + player.SendMessage("Error: Your item (" + item.name + ") (" + inventory[i].stack + ") needs to have it's stack decreased to (" + playerData.inventory[i].stack + ").", Color.Cyan); + check = false; + } + } + } + else + { + Item item = new Item(); + Item serverItem = new Item(); + if (armor[i - 48] != null && armor[i - 48].netID != 0) + { + if (playerData.inventory[i].netID != armor[i - 48].netID) + { + item.netDefaults(armor[i - 48].netID); + item.Prefix(armor[i - 48].prefix); + item.AffixName(); + player.SendMessage("Error: Your armor (" + item.name + ") needs to be deleted.", Color.Cyan); + check = false; + } + else if (playerData.inventory[i].prefix != armor[i - 48].prefix) + { + item.netDefaults(armor[i - 48].netID); + item.Prefix(armor[i - 48].prefix); + item.AffixName(); + player.SendMessage("Error: Your armor (" + item.name + ") needs to be deleted.", Color.Cyan); + check = false; + } + else if (armor[i - 48].stack > playerData.inventory[i].stack) + { + item.netDefaults(armor[i - 48].netID); + item.Prefix(armor[i - 48].prefix); + item.AffixName(); + player.SendMessage("Error: Your armor (" + item.name + ") (" + inventory[i].stack + ") needs to have it's stack decreased to (" + playerData.inventory[i].stack + ").", Color.Cyan); + check = false; + } + } + } + } + + return check; + } + + public static bool CheckIgnores(TSPlayer player) + { + bool check = false; + if (player.IgnoreActionsForPvP) + check = true; + if (player.IgnoreActionsForInventory) + check = true; + if (player.IgnoreActionsForCheating) + check = true; + return check; + } + public static bool CheckPlayerCollision(int x, int y) { if (x + 1 <= Main.maxTilesX && y + 3 <= Main.maxTilesY @@ -878,7 +1175,7 @@ namespace TShockAPI { for (int h = y; h < y + 4; h++) { - if (!Main.tile[i, h].active || !GetDataHandlers.BlacklistTiles[Main.tile[i, h].type]) + if (!Main.tile[i, h].active || !Main.tileSolid[Main.tile[i, h].type]) return false; } } @@ -904,12 +1201,12 @@ namespace TShockAPI Netplay.serverPort = file.ServerPort; } - Netplay.spamCheck = file.SpamChecks; + Netplay.spamCheck = false; RconHandler.Password = file.RconPassword; RconHandler.ListenPort = file.RconPort; - Tools.HashAlgo = file.HashAlgorithm; + TShock.Utils.HashAlgo = file.HashAlgorithm; } } } \ No newline at end of file diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index cfebb727..3d024668 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -32,7 +32,7 @@ true full false - ..\..\..\Downloads\TShock 3.3.4.924\ServerPlugins\ + ..\..\..\Tshock Debug\ServerPlugins\ DEBUG;TRACE prompt 4 @@ -48,13 +48,12 @@ true - - False - ..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll - ..\HttpBins\HttpServer.dll + + ..\SqlBins\Mono.Data.Sqlite.dll + False ..\SqlBins\MySql.Data.dll @@ -85,6 +84,7 @@ + @@ -125,7 +125,7 @@ - + diff --git a/TShockAPI/Tools.cs b/TShockAPI/Utils.cs old mode 100755 new mode 100644 similarity index 79% rename from TShockAPI/Tools.cs rename to TShockAPI/Utils.cs index 28915d61..dbb828ba --- a/TShockAPI/Tools.cs +++ b/TShockAPI/Utils.cs @@ -29,9 +29,9 @@ using Terraria; namespace TShockAPI { - public class Tools + public class Utils { - public static Random Random = new Random(); + public Random Random = new Random(); //private static List groups = new List(); /// @@ -39,7 +39,7 @@ namespace TShockAPI /// /// A string IPv4 address in IP:PORT form. /// A string IPv4 address. - public static string GetRealIP(string mess) + public string GetRealIP(string mess) { return mess.Split(':')[0]; } @@ -48,7 +48,7 @@ namespace TShockAPI /// Used for some places where a list of players might be used. /// /// String of players seperated by commas. - public static string GetPlayers() + public string GetPlayers() { var sb = new StringBuilder(); foreach (TSPlayer player in TShock.Players) @@ -69,7 +69,7 @@ namespace TShockAPI /// Finds a player and gets IP as string /// /// Player name - public static string GetPlayerIP(string playername) + public string GetPlayerIP(string playername) { foreach (TSPlayer player in TShock.Players) { @@ -92,7 +92,7 @@ namespace TShockAPI /// Maximum bounds of the clamp /// Minimum bounds of the clamp /// - public static T Clamp(T value, T max, T min) + public T Clamp(T value, T max, T min) where T : IComparable { T result = value; @@ -106,7 +106,7 @@ namespace TShockAPI /// /// Saves the map data /// - public static void SaveWorld() + public void SaveWorld() { WorldGen.saveWorld(); Broadcast("World saved.", Color.Yellow); @@ -117,19 +117,19 @@ namespace TShockAPI /// Broadcasts a message to all players /// /// string message - public static void Broadcast(string msg) + public void Broadcast(string msg) { Broadcast(msg, Color.Green); } - public static void Broadcast(string msg, byte red, byte green, byte blue) + public void Broadcast(string msg, byte red, byte green, byte blue) { TSPlayer.All.SendMessage(msg, red, green, blue); TSPlayer.Server.SendMessage(msg, red, green, blue); Log.Info(string.Format("Broadcast: {0}", msg)); } - public static void Broadcast(string msg, Color color) + public void Broadcast(string msg, Color color) { Broadcast(msg, color.R, color.G, color.B); } @@ -139,7 +139,7 @@ namespace TShockAPI /// /// /// - public static void SendLogs(string log, Color color) + public void SendLogs(string log, Color color) { Log.Info(log); TSPlayer.Server.SendMessage(log, color); @@ -154,7 +154,7 @@ namespace TShockAPI /// The number of active players on the server. /// /// int playerCount - public static int ActivePlayers() + public int ActivePlayers() { int num = 0; foreach (TSPlayer player in TShock.Players) @@ -172,7 +172,7 @@ namespace TShockAPI /// /// /// - public static List FindPlayer(string ply) + public List FindPlayer(string ply) { var found = new List(); ply = ply.ToLower(); @@ -190,7 +190,7 @@ namespace TShockAPI return found; } - public static void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, out int tileX, out int tileY) + public void GetRandomClearTileWithInRange(int startTileX, int startTileY, int tileXRange, int tileYRange, out int tileX, out int tileY) { int j = 0; do @@ -209,17 +209,17 @@ namespace TShockAPI while (TileValid(tileX, tileY) && !TileClear(tileX, tileY)); } - private static bool TileValid(int tileX, int tileY) + private bool TileValid(int tileX, int tileY) { return tileX >= 0 && tileX <= Main.maxTilesX && tileY >= 0 && tileY <= Main.maxTilesY; } - private static bool TileClear(int tileX, int tileY) + private bool TileClear(int tileX, int tileY) { return !Main.tile[tileX, tileY].active; } - public static List GetItemByIdOrName(string idOrName) + public List GetItemByIdOrName(string idOrName) { int type = -1; if (int.TryParse(idOrName, out type)) @@ -229,14 +229,14 @@ namespace TShockAPI return GetItemByName(idOrName); } - public static Item GetItemById(int id) + public Item GetItemById(int id) { Item item = new Item(); - item.SetDefaults(id); + item.netDefaults(id); return item; } - public static List GetItemByName(string name) + public List GetItemByName(string name) { //Method #1 - must be exact match, allows support for different pickaxes/hammers/swords etc for (int i = 1; i < Main.maxItemTypes; i++) @@ -248,12 +248,12 @@ namespace TShockAPI } //Method #2 - allows impartial matching var found = new List(); - for (int i = 1; i < Main.maxItemTypes; i++) + for (int i = -24; i < Main.maxItemTypes; i++) { try { Item item = new Item(); - item.SetDefaults(i); + item.netDefaults(i); if (item.name.ToLower() == name.ToLower()) return new List { item }; if (item.name.ToLower().StartsWith(name.ToLower())) @@ -264,7 +264,7 @@ namespace TShockAPI return found; } - public static List GetNPCByIdOrName(string idOrName) + public List GetNPCByIdOrName(string idOrName) { int type = -1; if (int.TryParse(idOrName, out type)) @@ -274,17 +274,17 @@ namespace TShockAPI return GetNPCByName(idOrName); } - public static NPC GetNPCById(int id) + public NPC GetNPCById(int id) { NPC npc = new NPC(); - npc.SetDefaults(id); + npc.netDefaults(id); return npc; } - public static List GetNPCByName(string name) + public List GetNPCByName(string name) { //Method #1 - must be exact match, allows support for different coloured slimes - for (int i = 1; i < Main.maxNPCTypes; i++) + for (int i = -17; i < Main.maxNPCTypes; i++) { NPC npc = new NPC(); npc.SetDefaults(name); @@ -296,7 +296,7 @@ namespace TShockAPI for (int i = 1; i < Main.maxNPCTypes; i++) { NPC npc = new NPC(); - npc.SetDefaults(i); + npc.netDefaults(i); if (npc.name.ToLower() == name.ToLower()) return new List { npc }; if (npc.name.ToLower().StartsWith(name.ToLower())) @@ -305,15 +305,17 @@ namespace TShockAPI return found; } - public static string GetBuffName(int id) + public string GetBuffName(int id) { return (id > 0 && id < Main.maxBuffs) ? Main.buffName[id] : "null"; } - public static string GetBuffDescription(int id) + + public string GetBuffDescription(int id) { return (id > 0 && id < Main.maxBuffs) ? Main.buffTip[id] : "null"; } - public static List GetBuffByName(string name) + + public List GetBuffByName(string name) { for (int i = 1; i < Main.maxBuffs; i++) { @@ -329,12 +331,57 @@ namespace TShockAPI return found; } + public string GetPrefixById(int id) + { + var item = new Item(); + item.SetDefaults(0); + item.prefix = (byte)id; + item.AffixName(); + return item.name.Trim(); + } + + public List GetPrefixByName(string name) + { + Item item = new Item(); + item.SetDefaults(0); + for (int i = 1; i < 83; i++) + { + item.prefix = (byte) i; + if (item.AffixName().Trim() == name) + return new List { i }; + } + var found = new List(); + for (int i = 1; i < 83; i++) + { + try + { + item.prefix = (byte) i; + if (item.AffixName().Trim().ToLower() == name.ToLower()) + return new List { i }; + if (item.AffixName().Trim().ToLower().StartsWith(name.ToLower())) + found.Add(i); + } + catch { } + } + return found; + } + + public List GetPrefixByIdOrName(string idOrName) + { + int type = -1; + if (int.TryParse(idOrName, out type) && type > 0 && type < 84) + { + return new List {type}; + } + return GetPrefixByName(idOrName); + } + /// /// Kicks all player from the server without checking for immunetokick permission. /// /// int player /// string reason - public static void ForceKickAll(string reason) + public void ForceKickAll(string reason) { foreach (TSPlayer player in TShock.Players) { @@ -350,7 +397,7 @@ namespace TShockAPI /// /// int player /// string reason - public static void ForceKick(TSPlayer player, string reason) + public void ForceKick(TSPlayer player, string reason) { if (!player.ConnectionAlive) return; @@ -363,7 +410,7 @@ namespace TShockAPI /// /// int player /// string reason - public static bool Kick(TSPlayer player, string reason, string adminUserName = "") + public bool Kick(TSPlayer player, string reason, string adminUserName = "") { if (!player.ConnectionAlive) return true; @@ -386,7 +433,7 @@ namespace TShockAPI /// /// int player /// string reason - public static bool Ban(TSPlayer player, string reason, string adminUserName = "") + public bool Ban(TSPlayer player, string reason, string adminUserName = "") { if (!player.ConnectionAlive) return true; @@ -406,49 +453,13 @@ namespace TShockAPI return false; } - public static bool HandleCheater(TSPlayer player, string reason) - { - return HandleBadPlayer(player, "ignorecheatdetection", TShock.Config.BanCheaters, TShock.Config.KickCheaters, reason); - } - - public static bool HandleGriefer(TSPlayer player, string reason) - { - return HandleBadPlayer(player, Permissions.ignoregriefdetection, TShock.Config.BanGriefers, TShock.Config.KickGriefers, reason); - } - - public static bool HandleTntUser(TSPlayer player, string reason) - { - return HandleBadPlayer(player, Permissions.ignoregriefdetection, TShock.Config.BanKillTileAbusers, TShock.Config.KickKillTileAbusers, reason); - } - - public static bool HandleExplosivesUser(TSPlayer player, string reason) - { - return HandleBadPlayer(player, Permissions.ignoregriefdetection, TShock.Config.BanExplosives, TShock.Config.KickExplosives, reason); - } - - private static bool HandleBadPlayer(TSPlayer player, string overridePermission, bool ban, bool kick, string reason) - { - if (!player.Group.HasPermission(overridePermission) || !(player.Group.Name == "superadmin")) - { - if (ban) - { - return Ban(player, reason); - } - if (kick) - { - return Kick(player, reason); - } - } - return false; - } - /// /// Shows a file to the user. /// /// int player /// string filename reletave to savedir //Todo: Fix this - public static void ShowFileToUser(TSPlayer player, string file) + public void ShowFileToUser(TSPlayer player, string file) { string foo = ""; using (var tr = new StreamReader(Path.Combine(TShock.SavePath, file))) @@ -487,7 +498,7 @@ namespace TShockAPI /// Returns a Group from the name of the group /// /// string groupName - public static Group GetGroup(string groupName) + public Group GetGroup(string groupName) { //first attempt on cached groups for (int i = 0; i < TShock.Groups.groups.Count; i++) @@ -504,7 +515,7 @@ namespace TShockAPI /// Returns an IPv4 address from a DNS query /// /// string ip - public static string GetIPv4Address(string hostname) + public string GetIPv4Address(string hostname) { try { @@ -519,9 +530,9 @@ namespace TShockAPI return ""; } - public static string HashAlgo = "md5"; + public string HashAlgo = "md5"; - public static readonly Dictionary> HashTypes = new Dictionary> + public readonly Dictionary> HashTypes = new Dictionary> { {"sha512", () => new SHA512Managed()}, {"sha256", () => new SHA256Managed()}, @@ -536,7 +547,7 @@ namespace TShockAPI /// /// bytes to hash /// string sha256 - public static string HashPassword(byte[] bytes) + public string HashPassword(byte[] bytes) { if (bytes == null) throw new NullReferenceException("bytes"); @@ -555,7 +566,7 @@ namespace TShockAPI /// /// bytes to hash /// string sha256 - public static string HashPassword(string password) + public string HashPassword(string password) { if (string.IsNullOrEmpty(password) || password == "non-existant password") return "non-existant password"; @@ -567,7 +578,7 @@ namespace TShockAPI /// /// String to check /// True if the string only contains printable characters - public static bool ValidString(string str) + public bool ValidString(string str) { foreach (var c in str) { @@ -581,7 +592,7 @@ namespace TShockAPI /// Checks if world has hit the max number of chests /// /// True if the entire chest array is used - public static bool MaxChests() + public bool MaxChests() { for (int i = 0; i < Main.chest.Length; i++) { @@ -590,5 +601,15 @@ namespace TShockAPI } return true; } + + public int SearchProjectile(short identity) + { + for (int i = 0; i < Main.maxProjectiles; i++) + { + if (Main.projectile[i].identity == identity) + return i; + } + return 1000; + } } } diff --git a/TShockAPI/postbuild.bat b/TShockAPI/postbuild.bat index 65a20215..1ecae508 100644 --- a/TShockAPI/postbuild.bat +++ b/TShockAPI/postbuild.bat @@ -1,4 +1,3 @@ -@echo off set pluginspath=C:\Program Files (x86)\Steam\steamapps\common\terraria\serverplugins\ IF NOT EXIST "%pluginspath%" GOTO SkipCopy attrib -r "%pluginspath%TShockAPI.dll" diff --git a/TerrariaServerBins/TerrariaServer.exe b/TerrariaServerBins/TerrariaServer.exe index c59f4d25..69f1b216 100644 Binary files a/TerrariaServerBins/TerrariaServer.exe and b/TerrariaServerBins/TerrariaServer.exe differ diff --git a/UnitTests/BanManagerTest.cs b/UnitTests/BanManagerTest.cs index d18ca714..aebeaf38 100644 --- a/UnitTests/BanManagerTest.cs +++ b/UnitTests/BanManagerTest.cs @@ -3,7 +3,7 @@ using System.Data; using System.Text; using System.Collections.Generic; using System.Linq; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using Microsoft.VisualStudio.TestTools.UnitTesting; using TShockAPI; using TShockAPI.DB; diff --git a/UnitTests/GroupManagerTest.cs b/UnitTests/GroupManagerTest.cs index b38eb2ae..2e4efc1d 100644 --- a/UnitTests/GroupManagerTest.cs +++ b/UnitTests/GroupManagerTest.cs @@ -3,7 +3,7 @@ using System.Data; using System.Text; using System.Collections.Generic; using System.Linq; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using Microsoft.VisualStudio.TestTools.UnitTesting; using TShockAPI; using TShockAPI.DB; @@ -40,7 +40,7 @@ namespace UnitTests { Assert.IsTrue(Groups.AddGroup("test1", "heal") != ""); Assert.IsTrue(Groups.GroupExists("test1")); - Assert.IsTrue(Tools.GetGroup("test1").HasPermission("heal")); + Assert.IsTrue(TShock.Utils.GetGroup("test1").HasPermission("heal")); } [TestMethod] diff --git a/UnitTests/ItemManagerTest.cs b/UnitTests/ItemManagerTest.cs index ef6ed314..7e19d5d6 100644 --- a/UnitTests/ItemManagerTest.cs +++ b/UnitTests/ItemManagerTest.cs @@ -10,7 +10,7 @@ using System.Diagnostics; using System.Net; using System.Reflection; using System.Threading; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using TShockAPI.DB; using TShockAPI; diff --git a/UnitTests/RegionManagerTest.cs b/UnitTests/RegionManagerTest.cs index 8fd1ea08..a8620117 100644 --- a/UnitTests/RegionManagerTest.cs +++ b/UnitTests/RegionManagerTest.cs @@ -5,7 +5,7 @@ using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Data; using TShockAPI; -using Community.CsharpSqlite.SQLiteClient; +using Mono.Data.Sqlite; using TShockAPI.DB; using Region = TShockAPI.DB.Region; diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index d8e57ddc..ef72520c 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -48,13 +48,10 @@ 4 - - ..\SqlBins\Community.CsharpSqlite.dll - - - ..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll - + + ..\SqlBins\Mono.Data.Sqlite.dll + ..\SqlBins\MySql.Data.dll @@ -128,6 +125,9 @@ + + xcopy .\..\..\..\SqlBins\sqlite3.dll . /Y +