Merge branch 'general-devel'

Conflicts:
	TShockAPI/Properties/AssemblyInfo.cs
	TShockAPI/Utils.cs
This commit is contained in:
Lucas Nicodemus 2011-12-21 11:40:18 -07:00
commit b22534efd3
40 changed files with 2169 additions and 788 deletions

View file

@ -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)

View file

@ -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;

View file

@ -26,6 +26,7 @@
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@ -49,8 +50,8 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Community.CsharpSqlite.SQLiteClient">
<HintPath>..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll</HintPath>
<Reference Include="Mono.Data.Sqlite">
<HintPath>..\SqlBins\Mono.Data.Sqlite.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

196
SqlBins/sqlite3.def Normal file
View file

@ -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

BIN
SqlBins/sqlite3.dll Normal file

Binary file not shown.

View file

@ -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)

View file

@ -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 <day/night/dusk/noon/midnight>", 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 <username>:<password> superadmin");
args.Player.SendMessage("Creates: <username> with the password <password> as part of the superadmin group.");
@ -2202,7 +2393,7 @@ namespace TShockAPI
args.Player.SendMessage("Invalid syntax! Proper syntax: /me <text>", 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 name/id> [item amount]", Color.Red);
args.Player.SendMessage("Invalid syntax! Proper syntax: /item <item name/id> [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 type/id> <player> [item amount]", Color.Red);
args.Player.SendMessage("Invalid syntax! Proper syntax: /give <item type/id> <player> [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);

View file

@ -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) <TerrariaDude): Hi!")]
public string AdminChatPrefix = "(Admin) ";
[Description("")]
public bool AdminChatEnabled = true;
[Description("Seconds a player has to wait between pvp toggles.")]
public int PvpThrottle;
[Description("Backup frequency in minutes. So, a value of 60 = 60 minutes. Backups are stored in the \\tshock\\backups folder.")]
public int BackupInterval;
[Description("How long backups are kept in minutes. 2880 = 2 days.")]
@ -127,34 +103,10 @@ namespace TShockAPI
[Description("")]
public string MySqlPassword = "";
[Description("")]
public string RangeCheckBanReason = "Placing impossible to place blocks.";
[Description("")]
public string SendSectionAbuseReason = "SendSection abuse.";
[Description("")]
public string NPCSpawnAbuseReason = "Spawn NPC abuse";
[Description("")]
public string UpdatePlayerAbuseReason = "Update Player abuse";
[Description("")]
public string ExplosiveAbuseReason = "Throwing an explosive device.";
[Description("")]
public string KillMeAbuseReason = "Trying to execute KillMe on someone else.";
[Description("")]
public string IllogicalLiquidUseReason = "Manipulating liquid without bucket.";
[Description("")]
public string LiquidAbuseReason = "Placing impossible to place liquid.";
[Description("")]
public string TileKillAbuseReason = "Tile Kill abuse ({0})";
[Description("")]
public string MediumcoreBanReason = "Death results in a ban";
[Description("")]
public string MediumcoreKickReason = "Death results in a kick";
[Description("")]
public string ProjectileAbuseReason = "Projectile abuse";
[Description("")]
public string TileAbuseReason = "Tile abuse ({0})";
[Description("")]
public string GriefClientReason = "Grief client detected ({0})";
[Description("")]
public bool EnableDNSHostResolution;
[Description("")]
public bool EnableBanOnUsernames;
@ -181,9 +133,6 @@ namespace TShockAPI
[Description("This will save the world if Terraria crashes from an unhandled exception.")]
public bool SaveWorldOnCrash = true;
[Description("This is kick players who have custom items in their inventory (via a mod)")]
public bool KickCustomItems = false;
[Description("This will announce a player's location on join")]
public bool EnableGeoIP = false;
@ -199,6 +148,33 @@ namespace TShockAPI
[Description("This is the port which the rest api will listen on.")]
public int RestApiPort = 7878;
[Description("Disable tombstones for all players.")]
public bool DisableTombstones = true;
[Description("Displays a player's IP on join to everyone who has the log permission")]
public bool DisplayIPToAdmins = false;
[Description("Some tiles are 'fixed' by not letting TShock handle them. Disabling this may break certain asthetic tiles.")]
public bool EnableInsecureTileFixes = true;
[Description("Kicks users using a proxy as identified with the GeoIP database")]
public bool KickProxyUsers = true;
[Description("Kicks banned users by their name")]
public bool EnableNameBans = false;
[Description("Kicks banned users by their IP")]
public bool EnableIPBans = true;
[Description("Disables hardmode, can't never be activated. Overrides /starthardmode")]
public bool DisableHardmode = false;
[Description("Disables Dungeon Guardian from being spawned by player packets, this will instead force a respawn")]
public bool DisableDungeonGuardian = false;
[Description("Enable Server Side Inventory checks, EXPERIMENTAL")]
public bool ServerSideInventory = false;
public static ConfigFile Read(string path)
{
if (!File.Exists(path))

View file

@ -27,11 +27,11 @@ namespace TShockAPI.DB
creator.EnsureExists(table);
//Add default groups
AddGroup("default", "canwater,canlava,warp,canbuild");
AddGroup("default", "warp,canbuild");
AddGroup("newadmin", "default", "kick,editspawn,reservedslot");
AddGroup("admin", "newadmin", "ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere");
AddGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,ignorecheatdetection,ignoregriefdetection,usebanneditem,manageusers");
AddGroup("vip", "default", "canwater,canlava,warp,canbuild,reservedslot");
AddGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,usebanneditem,manageusers");
AddGroup("vip", "default", "reservedslot");
String file = Path.Combine(TShock.SavePath, "groups.txt");
if (File.Exists(file))
@ -138,7 +138,7 @@ namespace TShockAPI.DB
if (database.Query("DELETE FROM GroupList WHERE GroupName=@0", name) == 1)
message = "Group " + name + " has been deleted successfully.";
groups.Remove(Tools.GetGroup(name));
groups.Remove(TShock.Utils.GetGroup(name));
return message;
}
@ -149,7 +149,7 @@ namespace TShockAPI.DB
if (!GroupExists(name))
return "Error: Group doesn't exists.";
var group = Tools.GetGroup(name);
var group = TShock.Utils.GetGroup(name);
//Add existing permissions (without duplicating)
permissions.AddRange(group.permissions.Where(s => !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 );

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<int>("MaxHealth");
playerData.maxMana = reader.Get<int>("MaxMana");
playerData.inventory = NetItem.Parse(reader.Get<string>("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;
}
}
}

View file

@ -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)

View file

@ -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<string>("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<string>("IP")) == ip)
if (TShock.Utils.GetIPv4Address(reader.Get<string>("IP")) == ip)
{
return Tools.GetGroup(reader.Get<string>("UserGroup"));
return TShock.Utils.GetGroup(reader.Get<string>("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");
}

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -131,6 +131,14 @@ namespace TShockAPI
Write(message, LogLevel.Debug);
}
/// <summary>
/// Disposes objects that are being used.
/// </summary>
public static void Dispose()
{
_logWriter.Dispose();
}
/// <summary>
/// Internal method which writes a message directly to the log file.
/// </summary>

View file

@ -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

View file

@ -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
}
}

View file

@ -32,6 +32,8 @@ namespace TShockAPI.Net
DownedBoss1 = 2,
DownedBoss2 = 4,
DownedBoss3 = 8,
HardMode = 16,
DownedClown = 32
}
public class WorldInfoMsg : BaseMsg
{

View file

@ -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;
}

View file

@ -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())

View file

@ -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")]
[assembly: AssemblyVersion("3.4.0.1221")]
[assembly: AssemblyFileVersion("3.4.0.1221")]

View file

@ -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.";

View file

@ -329,7 +329,7 @@ namespace TShockAPI
{
var returnBlock = new Dictionary<string, object>();
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<string, object>();
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<string, object>();
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");
}

View file

@ -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<Vector2, TileData> TilesDestroyed { get; protected set; }
public Dictionary<Vector2, Tile> 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;
}
}
/// <summary>
@ -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<Vector2, TileData>();
TilesDestroyed = new Dictionary<Vector2, Tile>();
Index = index;
Group = new Group("null");
}
protected TSPlayer(String playerName)
{
TilesDestroyed = new Dictionary<Vector2, TileData>();
TilesDestroyed = new Dictionary<Vector2, Tile>();
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<Vector2, TileData> destroyedTiles)
public void RevertKillTile(Dictionary<Vector2, Tile> destroyedTiles)
{
// Update Main.Tile first so that when tile sqaure is sent it is correct
foreach (KeyValuePair<Vector2, TileData> entry in destroyedTiles)
foreach (KeyValuePair<Vector2, Tile> 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;
}
}
}

View file

@ -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();
/// <summary>
/// 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<Projectile, int> e)
{
if (e.Info == 43)
if (Config.DisableTombstones)
e.Object.SetDefaults(0);
}
/// <summary>
/// Send bytes to client using packetbuffering if available
/// </summary>
@ -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;
}
}
}

View file

@ -32,7 +32,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\Downloads\TShock 3.3.4.924\ServerPlugins\</OutputPath>
<OutputPath>..\..\..\Tshock Debug\ServerPlugins\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -48,13 +48,12 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Community.CsharpSqlite.SQLiteClient, Version=3.7.5.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll</HintPath>
</Reference>
<Reference Include="HttpServer">
<HintPath>..\HttpBins\HttpServer.dll</HintPath>
</Reference>
<Reference Include="Mono.Data.Sqlite">
<HintPath>..\SqlBins\Mono.Data.Sqlite.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\SqlBins\MySql.Data.dll</HintPath>
@ -85,6 +84,7 @@
<ItemGroup>
<Compile Include="BackupManager.cs" />
<Compile Include="DB\BanManager.cs" />
<Compile Include="DB\InventoryManager.cs" />
<Compile Include="DB\IQueryBuilder.cs" />
<Compile Include="DB\ItemManager.cs" />
<Compile Include="DB\SqlColumn.cs" />
@ -125,7 +125,7 @@
<Compile Include="Rest\RestObject.cs" />
<Compile Include="Rest\RestVerbs.cs" />
<Compile Include="Rest\SecureRest.cs" />
<Compile Include="Tools.cs" />
<Compile Include="Utils.cs" />
<Compile Include="TShock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TSPlayer.cs" />

181
TShockAPI/Tools.cs → TShockAPI/Utils.cs Executable file → Normal file
View file

@ -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<Group> groups = new List<Group>();
/// <summary>
@ -39,7 +39,7 @@ namespace TShockAPI
/// </summary>
/// <param name="mess">A string IPv4 address in IP:PORT form.</param>
/// <returns>A string IPv4 address.</returns>
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.
/// </summary>
/// <returns>String of players seperated by commas.</returns>
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
/// </summary>
/// <param name="msg">Player name</param>
public static string GetPlayerIP(string playername)
public string GetPlayerIP(string playername)
{
foreach (TSPlayer player in TShock.Players)
{
@ -92,7 +92,7 @@ namespace TShockAPI
/// <param name="max">Maximum bounds of the clamp</param>
/// <param name="min">Minimum bounds of the clamp</param>
/// <returns></returns>
public static T Clamp<T>(T value, T max, T min)
public T Clamp<T>(T value, T max, T min)
where T : IComparable<T>
{
T result = value;
@ -106,7 +106,7 @@ namespace TShockAPI
/// <summary>
/// Saves the map data
/// </summary>
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
/// </summary>
/// <param name="msg">string message</param>
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
/// </summary>
/// <param name="log"></param>
/// <param name="color"></param>
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.
/// </summary>
/// <returns>int playerCount</returns>
public static int ActivePlayers()
public int ActivePlayers()
{
int num = 0;
foreach (TSPlayer player in TShock.Players)
@ -172,7 +172,7 @@ namespace TShockAPI
/// </summary>
/// <param name="ply"></param>
/// <returns></returns>
public static List<TSPlayer> FindPlayer(string ply)
public List<TSPlayer> FindPlayer(string ply)
{
var found = new List<TSPlayer>();
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<Item> GetItemByIdOrName(string idOrName)
public List<Item> 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<Item> GetItemByName(string name)
public List<Item> 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<Item>();
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> { item };
if (item.name.ToLower().StartsWith(name.ToLower()))
@ -264,7 +264,7 @@ namespace TShockAPI
return found;
}
public static List<NPC> GetNPCByIdOrName(string idOrName)
public List<NPC> 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<NPC> GetNPCByName(string name)
public List<NPC> 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> { 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<int> GetBuffByName(string name)
public List<int> 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<int> 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<int> { i };
}
var found = new List<int>();
for (int i = 1; i < 83; i++)
{
try
{
item.prefix = (byte) i;
if (item.AffixName().Trim().ToLower() == name.ToLower())
return new List<int> { i };
if (item.AffixName().Trim().ToLower().StartsWith(name.ToLower()))
found.Add(i);
}
catch { }
}
return found;
}
public List<int> GetPrefixByIdOrName(string idOrName)
{
int type = -1;
if (int.TryParse(idOrName, out type) && type > 0 && type < 84)
{
return new List<int> {type};
}
return GetPrefixByName(idOrName);
}
/// <summary>
/// Kicks all player from the server without checking for immunetokick permission.
/// </summary>
/// <param name="ply">int player</param>
/// <param name="reason">string reason</param>
public static void ForceKickAll(string reason)
public void ForceKickAll(string reason)
{
foreach (TSPlayer player in TShock.Players)
{
@ -350,7 +397,7 @@ namespace TShockAPI
/// </summary>
/// <param name="ply">int player</param>
/// <param name="reason">string reason</param>
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
/// </summary>
/// <param name="ply">int player</param>
/// <param name="reason">string reason</param>
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
/// </summary>
/// <param name="ply">int player</param>
/// <param name="reason">string reason</param>
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;
}
/// <summary>
/// Shows a file to the user.
/// </summary>
/// <param name="ply">int player</param>
/// <param name="file">string filename reletave to savedir</param>
//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
/// </summary>
/// <param name="ply">string groupName</param>
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
/// </summary>
/// <param name="hostname">string ip</param>
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<string, Func<HashAlgorithm>> HashTypes = new Dictionary<string, Func<HashAlgorithm>>
public readonly Dictionary<string, Func<HashAlgorithm>> HashTypes = new Dictionary<string, Func<HashAlgorithm>>
{
{"sha512", () => new SHA512Managed()},
{"sha256", () => new SHA256Managed()},
@ -536,7 +547,7 @@ namespace TShockAPI
/// </summary>
/// <param name="bytes">bytes to hash</param>
/// <returns>string sha256</returns>
public static string HashPassword(byte[] bytes)
public string HashPassword(byte[] bytes)
{
if (bytes == null)
throw new NullReferenceException("bytes");
@ -555,7 +566,7 @@ namespace TShockAPI
/// </summary>
/// <param name="bytes">bytes to hash</param>
/// <returns>string sha256</returns>
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
/// </summary>
/// <param name="str">String to check</param>
/// <returns>True if the string only contains printable characters</returns>
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
/// </summary>
/// <returns>True if the entire chest array is used</returns>
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;
}
}
}

View file

@ -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"

View file

@ -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;

View file

@ -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]

View file

@ -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;

View file

@ -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;

View file

@ -48,13 +48,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Community.CsharpSqlite">
<HintPath>..\SqlBins\Community.CsharpSqlite.dll</HintPath>
</Reference>
<Reference Include="Community.CsharpSqlite.SQLiteClient">
<HintPath>..\SqlBins\Community.CsharpSqlite.SQLiteClient.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Mono.Data.Sqlite">
<HintPath>..\SqlBins\Mono.Data.Sqlite.dll</HintPath>
</Reference>
<Reference Include="MySql.Data">
<HintPath>..\SqlBins\MySql.Data.dll</HintPath>
</Reference>
@ -128,6 +125,9 @@
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy .\..\..\..\SqlBins\sqlite3.dll . /Y</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">