Merge branch 'general-devel' of github.com:TShock/TShock

Conflicts:
	DBEditor/Main.Designer.cs
	DBEditor/Main.cs
This commit is contained in:
high 2011-08-05 00:55:54 -04:00
commit 4cf35a3093
50 changed files with 2567 additions and 1506 deletions

1
.gitignore vendored
View file

@ -52,3 +52,4 @@ Thumbs.db
#Template Bat file#
###################
myass.bat
/TestResults

View file

@ -5,21 +5,23 @@ using System.Text;
namespace TShockDBEditor
{
public class Commandlist
public class TShockCommandsList
{
public static List<string> CommandList = new List<string>();
public static void AddRemainingTShockCommands()
{
List<string> CommandList = new List<string>();
public static void AddCommands()
{
CommandList.Add("reservedslot");
CommandList.Add("canwater");
CommandList.Add("canlava");
CommandList.Add("canbuild");
CommandList.Add("adminchat");
CommandList.Add("warp");
CommandList.Add("kick");
CommandList.Add("ban");
CommandList.Add("unban");
CommandList.Add("whitelist");
CommandList.Add("maintenace");
CommandList.Add("maintenance");
CommandList.Add("causeevents");
CommandList.Add("spawnboss");
CommandList.Add("spawnmob");
@ -42,6 +44,12 @@ namespace TShockDBEditor
CommandList.Add("ignorecheatdetection");
CommandList.Add("ignoregriefdetection");
CommandList.Add("usebanneditem");
foreach (string command in CommandList)
{
if (!TShockDBEditor.CommandList.Contains(command))
TShockDBEditor.CommandList.Add(command);
}
}
}
}

View file

@ -82,6 +82,8 @@
this.label14 = new System.Windows.Forms.Label();
this.lst_userlist = new System.Windows.Forms.ListBox();
this.tabPage6 = new System.Windows.Forms.TabPage();
this.groupBox7 = new System.Windows.Forms.GroupBox();
this.lst_bans = new System.Windows.Forms.ListBox();
this.groupBox6 = new System.Windows.Forms.GroupBox();
this.lbl_newbanstatus = new System.Windows.Forms.Label();
this.label16 = new System.Windows.Forms.Label();
@ -99,7 +101,6 @@
this.label19 = new System.Windows.Forms.Label();
this.txt_banreason = new System.Windows.Forms.TextBox();
this.label18 = new System.Windows.Forms.Label();
this.lst_bans = new System.Windows.Forms.ListBox();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.btn_OpenLocalDB = new System.Windows.Forms.Button();
@ -115,7 +116,6 @@
this.label7 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.groupBox7 = new System.Windows.Forms.GroupBox();
this.tabControl.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
@ -125,12 +125,12 @@
this.groupBox4.SuspendLayout();
this.groupBox3.SuspendLayout();
this.tabPage6.SuspendLayout();
this.groupBox7.SuspendLayout();
this.groupBox6.SuspendLayout();
this.groupBox5.SuspendLayout();
this.tabControl1.SuspendLayout();
this.tabPage3.SuspendLayout();
this.tabPage4.SuspendLayout();
this.groupBox7.SuspendLayout();
this.SuspendLayout();
//
// itemListBanned
@ -675,6 +675,25 @@
this.tabPage6.Text = "Ban Manager";
this.tabPage6.UseVisualStyleBackColor = true;
//
// groupBox7
//
this.groupBox7.Controls.Add(this.lst_bans);
this.groupBox7.Location = new System.Drawing.Point(6, 23);
this.groupBox7.Name = "groupBox7";
this.groupBox7.Size = new System.Drawing.Size(284, 352);
this.groupBox7.TabIndex = 13;
this.groupBox7.TabStop = false;
this.groupBox7.Text = "Ban List";
//
// lst_bans
//
this.lst_bans.FormattingEnabled = true;
this.lst_bans.Location = new System.Drawing.Point(6, 19);
this.lst_bans.Name = "lst_bans";
this.lst_bans.Size = new System.Drawing.Size(272, 329);
this.lst_bans.TabIndex = 0;
this.lst_bans.SelectedIndexChanged += new System.EventHandler(this.lst_bans_SelectedIndexChanged);
//
// groupBox6
//
this.groupBox6.Controls.Add(this.lbl_newbanstatus);
@ -839,15 +858,6 @@
this.label18.TabIndex = 4;
this.label18.Text = "Name:";
//
// lst_bans
//
this.lst_bans.FormattingEnabled = true;
this.lst_bans.Location = new System.Drawing.Point(6, 19);
this.lst_bans.Name = "lst_bans";
this.lst_bans.Size = new System.Drawing.Size(272, 329);
this.lst_bans.TabIndex = 0;
this.lst_bans.SelectedIndexChanged += new System.EventHandler(this.lst_bans_SelectedIndexChanged);
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage3);
@ -992,16 +1002,6 @@
this.label5.TabIndex = 0;
this.label5.Text = "Hostname:";
//
// groupBox7
//
this.groupBox7.Controls.Add(this.lst_bans);
this.groupBox7.Location = new System.Drawing.Point(6, 23);
this.groupBox7.Name = "groupBox7";
this.groupBox7.Size = new System.Drawing.Size(284, 352);
this.groupBox7.TabIndex = 13;
this.groupBox7.TabStop = false;
this.groupBox7.Text = "Ban List";
//
// TShockDBEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -1011,6 +1011,7 @@
this.Controls.Add(this.tabControl);
this.Name = "TShockDBEditor";
this.Text = "TShockDBEditor";
this.Load += new System.EventHandler(this.TShockDBEditor_Load);
this.tabControl.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage1.PerformLayout();
@ -1026,6 +1027,7 @@
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.tabPage6.ResumeLayout(false);
this.groupBox7.ResumeLayout(false);
this.groupBox6.ResumeLayout(false);
this.groupBox6.PerformLayout();
this.groupBox5.ResumeLayout(false);
@ -1034,7 +1036,6 @@
this.tabPage3.ResumeLayout(false);
this.tabPage4.ResumeLayout(false);
this.tabPage4.PerformLayout();
this.groupBox7.ResumeLayout(false);
this.ResumeLayout(false);
}

View file

@ -18,6 +18,7 @@ namespace TShockDBEditor
{
public OpenFileDialog dialog = new OpenFileDialog();
public List<Group> groups = new List<Group>();
public static List<string> CommandList = new List<string>();
public IDbConnection DB;
public string dbtype = "";
@ -25,7 +26,6 @@ namespace TShockDBEditor
{
InitializeComponent();
Itemlist.AddItems();
Commandlist.AddCommands();
dialog.FileOk += new CancelEventHandler(dialog_FileOk);
dialog.Filter = "SQLite Database (*.sqlite)|*.sqlite";
}
@ -50,6 +50,7 @@ namespace TShockDBEditor
itemListBanned.Items.Add(reader.Get<string>("ItemName"));
}
}
using (var com = DB.CreateCommand())
{
com.CommandText =
@ -68,6 +69,21 @@ namespace TShockDBEditor
lst_newusergrplist.Items.Add(reader.Get<string>("GroupName"));
}
}
using (var reader = com.ExecuteReader())
{
while (reader.Read())
{
foreach (string command in reader.Get<string>("Commands").Split(','))
{
if (!lst_groupList.Items.Contains(command))
if (!CommandList.Contains(command))
CommandList.Add(command);
}
}
}
TShockCommandsList.AddRemainingTShockCommands();
}
using (var com = DB.CreateCommand())
{
@ -203,7 +219,10 @@ namespace TShockDBEditor
private void lst_groupList_SelectedIndexChanged(object sender, EventArgs e)
{
if ((string)lst_groupList.SelectedItem != "superadmin")
UpdateGroupIndex(lst_groupList.SelectedIndex);
else
lst_groupList.SelectedIndex = -1;
}
private void UpdateGroupIndex(int index)
@ -238,10 +257,10 @@ namespace TShockDBEditor
if (lbl_grpchild.Text == "")
lbl_grpchild.Text = "none";
for (int i = 0; i < Commandlist.CommandList.Count; i++)
for (int i = 0; i < CommandList.Count; i++)
{
if (!lst_AvailableCmds.Items.Contains(Commandlist.CommandList[i]))
lst_bannedCmds.Items.Add(Commandlist.CommandList[i]);
if (!lst_AvailableCmds.Items.Contains(CommandList[i]))
lst_bannedCmds.Items.Add(CommandList[i]);
}
}
}
@ -535,6 +554,8 @@ namespace TShockDBEditor
#endregion
#region UserTab
private void lst_userlist_SelectedIndexChanged(object sender, EventArgs e)
{
txt_username.Text = "None Selected";
@ -728,5 +749,12 @@ namespace TShockDBEditor
return bytes.Aggregate("", (s, b) => s + b.ToString("X2"));
}
}
#endregion
private void TShockDBEditor_Load(object sender, EventArgs e)
{
}
}
}

View file

@ -26,7 +26,6 @@
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@ -75,8 +74,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Group.cs" />
<Compile Include="CommandList.cs" />
<Compile Include="Group.cs" />
<Compile Include="DbExt.cs" />
<Compile Include="Main.cs">
<SubType>Form</SubType>

View file

@ -1,5 +1,3 @@
####Do not download the latest master!
TShock is a server modification based upon High6's mod API that allows for basic server administration commands.
__Constant builds__: http://ci.tshock.co/

View file

@ -18,10 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Terraria;

View file

@ -1,4 +1,4 @@
/*
/*
TShock, a server mod for Terraria
Copyright (C) 2011 The TShock Team
@ -17,12 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework;
using Terraria;
@ -138,13 +137,16 @@ namespace TShockAPI
ChatCommands.Add(new Command("warp", UseWarp, "warp"));
ChatCommands.Add(new Command("managewarp", SetWarp, "setwarp"));
ChatCommands.Add(new Command("managewarp", DeleteWarp, "delwarp"));
ChatCommands.Add(new Command("managegroup", AddGroup, "addGroup"));
ChatCommands.Add(new Command("managegroup", DeleteGroup, "delGroup"));
ChatCommands.Add(new Command("managegroup", ModifyGroup, "modGroup"));
ChatCommands.Add(new Command("managewarp", HideWarp, "hidewarp"));
ChatCommands.Add(new Command("managegroup", AddGroup, "addgroup"));
ChatCommands.Add(new Command("managegroup", DeleteGroup, "delgroup"));
ChatCommands.Add(new Command("managegroup", ModifyGroup, "modgroup"));
ChatCommands.Add(new Command("manageitem", AddItem, "additem"));
ChatCommands.Add(new Command("manageitem", DeleteItem, "delitem"));
ChatCommands.Add(new Command("cfg", SetSpawn, "setspawn"));
ChatCommands.Add(new Command("cfg", Reload, "reload"));
ChatCommands.Add(new Command("cfg", DebugConfiguration, "debug-config"));
ChatCommands.Add(new Command("cfg", Password, "password"));
ChatCommands.Add(new Command("cfg", ShowConfiguration, "showconfig"));
ChatCommands.Add(new Command("cfg", ServerPassword, "serverpassword"));
ChatCommands.Add(new Command("cfg", Save, "save"));
ChatCommands.Add(new Command("cfg", MaxSpawns, "maxspawns"));
ChatCommands.Add(new Command("cfg", SpawnRate, "spawnrate"));
@ -370,7 +372,7 @@ namespace TShockAPI
catch (UserManagerException ex)
{
args.Player.SendMessage("Sorry, an error occured: " + ex.Message, Color.Green);
Log.ConsoleError("RegisterUser returned an error: " + ex.ToString());
Log.ConsoleError("RegisterUser returned an error: " + ex);
}
}
@ -383,7 +385,7 @@ namespace TShockAPI
var user = new User();
user.Name = args.Parameters[0].ToLower();
user.Password = args.Parameters[1];
user.Group = "default"; // FIXME -- we should get this from the DB.
user.Group = TShock.Config.DefaultRegistrationGroupName; // FIXME -- we should get this from the DB.
if (TShock.Users.GetUserByName(user.Name) == null) // Cheap way of checking for existance of a user
{
@ -406,7 +408,7 @@ namespace TShockAPI
catch (UserManagerException ex)
{
args.Player.SendMessage("Sorry, an error occured: " + ex.Message, Color.Green);
Log.ConsoleError("RegisterUser returned an error: " + ex.ToString());
Log.ConsoleError("RegisterUser returned an error: " + ex);
}
}
@ -414,15 +416,18 @@ namespace TShockAPI
private static void ManageUsers(CommandArgs args)
{
if (args.Parameters.Count < 2)
{
args.Player.SendMessage("Syntax: /user <add/del> <ip/user:pass> [group]");
args.Player.SendMessage("Note: Passwords are stored with SHA512 hashing. To reset a user's password, remove and re-add them.");
return;
}
// This guy needs to go away for the help later on to take effect.
//if (args.Parameters.Count < 2)
//{
// args.Player.SendMessage("Syntax: /user <add/del> <ip/user:pass> [group]");
// args.Player.SendMessage("Note: Passwords are stored with SHA512 hashing. To reset a user's password, remove and re-add them.");
// return;
//}
string subcmd = args.Parameters[0];
// Add requires a username:password pair/ip address and a group specified.
if (subcmd == "add")
{
var namepass = args.Parameters[1].Split(':');
@ -469,6 +474,7 @@ namespace TShockAPI
Log.ConsoleError(ex.ToString());
}
}
// User deletion requires a username
else if (subcmd == "del" && args.Parameters.Count == 2)
{
var user = new User();
@ -489,13 +495,86 @@ namespace TShockAPI
Log.ConsoleError(ex.ToString());
}
}
// Password changing requires a username, and a new password to set
else if (subcmd == "password")
{
var user = new User();
user.Name = args.Parameters[1];
try
{
if (args.Parameters.Count == 3)
{
args.Player.SendMessage("Changed the password of " + user.Name + "!", Color.Green);
TShock.Users.SetUserPassword(user, args.Parameters[2]);
Log.ConsoleInfo(args.Player.Name + " changed the password of Account " + user.Name);
}
else
{
args.Player.SendMessage("Invalid syntax. Try /user help.", Color.Red);
args.Player.SendMessage("Invalid user password syntax. Try /user help.", Color.Red);
}
}
catch (UserManagerException ex)
{
args.Player.SendMessage(ex.Message, Color.Green);
Log.ConsoleError(ex.ToString());
}
}
// Group changing requires a username or IP address, and a new group to set
else if (subcmd == "group")
{
var user = new User();
if (args.Parameters[1].Contains("."))
user.Address = args.Parameters[1];
else
user.Name = args.Parameters[1];
try
{
if (args.Parameters.Count == 3)
{
if (!string.IsNullOrEmpty(user.Address))
{
args.Player.SendMessage("IP Address " + user.Address + " has been changed to group " + args.Parameters[2] + "!", Color.Green);
TShock.Users.SetUserGroup(user, args.Parameters[2]);
Log.ConsoleInfo(args.Player.Name + " changed IP Address " + user.Address + " to group " + args.Parameters[2]);
}
else
{
args.Player.SendMessage("Account " + user.Name + " has been changed to group " + args.Parameters[2] + "!", Color.Green);
TShock.Users.SetUserGroup(user, args.Parameters[2]);
Log.ConsoleInfo(args.Player.Name + " changed Account " + user.Name + " to group " + args.Parameters[2]);
}
}
else
{
args.Player.SendMessage("Invalid user group syntax. Try /user help.", Color.Red);
}
}
catch (UserManagerException ex)
{
args.Player.SendMessage(ex.Message, Color.Green);
Log.ConsoleError(ex.ToString());
}
}
else if (subcmd == "help")
{
args.Player.SendMessage("Help for user subcommands:");
args.Player.SendMessage("/user add username:password group -- Adds a specified user");
args.Player.SendMessage("/user del username -- Removes a specified user");
args.Player.SendMessage("/user password username newpassword -- Changes a user's password");
args.Player.SendMessage("/user group username newgroup -- Changes a user's group");
}
else
{
args.Player.SendMessage("Invalid user syntax. Try /user help.", Color.Red);
}
}
#endregion
#region Player Management Commands
private static void GrabUserIP(CommandArgs args)
@ -626,7 +705,18 @@ namespace TShockAPI
if (TShock.Bans.RemoveBan(ban.IP))
args.Player.SendMessage(string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
else
args.Player.SendMessage(string.Format("Failed to Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
args.Player.SendMessage(string.Format("Failed to unban {0} ({1})!", ban.Name, ban.IP), Color.Red);
}
else if (!TShock.Config.EnableBanOnUsernames)
{
ban = TShock.Bans.GetBanByIp(plStr);
if (ban == null)
args.Player.SendMessage(string.Format("Failed to unban {0}, not found.", args.Parameters[0]), Color.Red);
else if (TShock.Bans.RemoveBan(ban.IP))
args.Player.SendMessage(string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
else
args.Player.SendMessage(string.Format("Failed to unban {0} ({1})!", ban.Name, ban.IP), Color.Red);
}
else
{
@ -695,7 +785,7 @@ namespace TShockAPI
if (TShock.Bans.RemoveBan(ban.IP))
args.Player.SendMessage(string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
else
args.Player.SendMessage(string.Format("Failed to Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
args.Player.SendMessage(string.Format("Failed to unban {0} ({1})!", ban.Name, ban.IP), Color.Red);
}
else
{
@ -859,7 +949,7 @@ namespace TShockAPI
return;
}
NPC eater = Tools.GetNPCById(13);
TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
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));
}
@ -878,7 +968,7 @@ namespace TShockAPI
}
NPC eye = Tools.GetNPCById(4);
TSPlayer.Server.SetTime(false, 0.0);
TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
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));
}
@ -896,7 +986,7 @@ namespace TShockAPI
return;
}
NPC king = Tools.GetNPCById(50);
TSPlayer.Server.SpawnNPC(king.type, king.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
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));
}
@ -915,7 +1005,7 @@ namespace TShockAPI
}
NPC skeletron = Tools.GetNPCById(35);
TSPlayer.Server.SetTime(false, 0.0);
TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
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));
}
@ -937,10 +1027,10 @@ namespace TShockAPI
NPC king = Tools.GetNPCById(50);
NPC skeletron = Tools.GetNPCById(35);
TSPlayer.Server.SetTime(false, 0.0);
TSPlayer.Server.SpawnNPC(eater.type, eater.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
TSPlayer.Server.SpawnNPC(eye.type, eye.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
TSPlayer.Server.SpawnNPC(king.type, king.name, amount, (int)args.Player.TileX, (int)args.Player.TileY);
TSPlayer.Server.SpawnNPC(skeletron.type, skeletron.name, amount, (int)args.Player.TileX, (int)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));
}
@ -977,7 +1067,7 @@ namespace TShockAPI
var npc = npcs[0];
if (npc.type >= 1 && npc.type < Main.maxNPCTypes)
{
TSPlayer.Server.SpawnNPC(npc.type, npc.name, amount, (int)args.Player.TileX, (int)args.Player.TileY, 50, 20);
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));
}
else
@ -1128,6 +1218,31 @@ namespace TShockAPI
args.Player.SendMessage("Invalid syntax! Proper syntax: /delwarp [name]", Color.Red);
}
private static void HideWarp(CommandArgs args)
{
if (args.Parameters.Count > 1)
{
string warpName = String.Join(" ", args.Parameters);
bool state = false;
if (Boolean.TryParse(args.Parameters[1], out state))
{
if (TShock.Warps.HideWarp(args.Parameters[0], state))
{
if (state)
args.Player.SendMessage("Made warp " + warpName + " private", Color.Yellow);
else
args.Player.SendMessage("Made warp " + warpName + " public", Color.Yellow);
}
else
args.Player.SendMessage("Could not find specified warp", Color.Red);
}
else
args.Player.SendMessage("Invalid syntax! Proper syntax: /hidewarp [name] <true/false>", Color.Red);
}
else
args.Player.SendMessage("Invalid syntax! Proper syntax: /hidewarp [name] <true/false>", Color.Red);
}
private static void UseWarp(CommandArgs args)
{
if (args.Parameters.Count < 1)
@ -1156,7 +1271,7 @@ namespace TShockAPI
page--; //Substract 1 as pages are parsed starting at 1 and not 0
}
var warps = TShock.Warps.ListAllWarps(Main.worldID.ToString());
var warps = TShock.Warps.ListAllPublicWarps(Main.worldID.ToString());
//Check if they are trying to access a page that doesn't exist.
int pagecount = warps.Count / pagelimit;
@ -1207,7 +1322,6 @@ namespace TShockAPI
#endregion Teleport Commands
#region Group Management
private static void AddGroup(CommandArgs args)
@ -1218,7 +1332,7 @@ namespace TShockAPI
args.Parameters.RemoveAt(0);
String permissions = String.Join(",", args.Parameters );
String response = TShock.Groups.addGroup(groupname, permissions);
String response = TShock.Groups.AddGroup(groupname, permissions);
if( response.Length > 0 )
args.Player.SendMessage(response, Color.Green);
}
@ -1234,7 +1348,7 @@ namespace TShockAPI
{
String groupname = args.Parameters[0];
String response = TShock.Groups.delGroup(groupname);
String response = TShock.Groups.DeleteGroup(groupname);
if (response.Length > 0)
args.Player.SendMessage(response, Color.Green);
}
@ -1256,14 +1370,14 @@ namespace TShockAPI
if (com.Equals("add"))
{
String response = TShock.Groups.addPermission(groupname, args.Parameters);
String response = TShock.Groups.AddPermissions(groupname, args.Parameters);
if (response.Length > 0)
args.Player.SendMessage(response, Color.Green);
return;
}
else if (com.Equals("del") || com.Equals("delete"))
{
String response = TShock.Groups.delPermission(groupname, args.Parameters);
String response = TShock.Groups.DeletePermissions(groupname, args.Parameters);
if (response.Length > 0)
args.Player.SendMessage(response, Color.Green);
return;
@ -1273,6 +1387,77 @@ namespace TShockAPI
}
#endregion Group Management
#region Item Management
private static void AddItem(CommandArgs args)
{
if (args.Parameters.Count > 0)
{
var items = Tools.GetItemByIdOrName(args.Parameters[0]);
if (items.Count == 0)
{
args.Player.SendMessage("Invalid item type!", Color.Red);
}
else if (items.Count > 1)
{
args.Player.SendMessage(string.Format("More than one ({0}) item matched!", items.Count), Color.Red);
}
else
{
var item = items[0];
if (item.type >= 1)
{
TShock.Itembans.AddNewBan(args.Parameters[0]);
args.Player.SendMessage(Tools.GetItemByIdOrName(args.Parameters[0])[0].name + " has been banned.", Color.Green);
}
else
{
args.Player.SendMessage("Invalid item type!", Color.Red);
}
}
}
else
{
args.Player.SendMessage("Invalid use: /addItem \"item name\" or /addItem ##", Color.Red);
}
}
private static void DeleteItem(CommandArgs args)
{
if (args.Parameters.Count > 0)
{
var items = Tools.GetItemByIdOrName(args.Parameters[0]);
if (items.Count == 0)
{
args.Player.SendMessage("Invalid item type!", Color.Red);
}
else if (items.Count > 1)
{
args.Player.SendMessage(string.Format("More than one ({0}) item matched!", items.Count), Color.Red);
}
else
{
var item = items[0];
if (item.type >= 1)
{
TShock.Itembans.RemoveBan(args.Parameters[0]);
args.Player.SendMessage(Tools.GetItemByIdOrName(args.Parameters[0])[0].name + " has been unbanned.", Color.Green);
}
else
{
args.Player.SendMessage("Invalid item type!", Color.Red);
}
}
}
else
{
args.Player.SendMessage("Invalid use: /delItem \"item name\" or /delItem ##", Color.Red);
}
}
#endregion Item Management
#region Server Config Commands
private static void SetSpawn(CommandArgs args)
@ -1285,7 +1470,7 @@ namespace TShockAPI
SaveWorld.Start();
}
private static void DebugConfiguration(CommandArgs args)
private static void ShowConfiguration(CommandArgs args)
{
args.Player.SendMessage("TShock Config:");
string lineOne = string.Format("BanCheater : {0}, KickCheater : {1}, BanGriefer : {2}, KickGriefer : {3}",
@ -1313,7 +1498,7 @@ namespace TShockAPI
args.Player.SendMessage("Configuration reload complete. Some changes may require server restart.");
}
private static void Password(CommandArgs args)
private static void ServerPassword(CommandArgs args)
{
if (args.Parameters.Count != 1)
{
@ -1465,10 +1650,10 @@ namespace TShockAPI
{
foreach (Region r in TShock.Regions.Regions)
{
args.Player.SendMessage(r.RegionName + ": P: " + r.DisableBuild + " X: " + r.RegionArea.X + " Y: " + r.RegionArea.Y + " W: " + r.RegionArea.Width + " H: " + r.RegionArea.Height);
foreach (int s in r.RegionAllowedIDs)
args.Player.SendMessage(r.Name + ": P: " + r.DisableBuild + " X: " + r.Area.X + " Y: " + r.Area.Y + " W: " + r.Area.Width + " H: " + r.Area.Height);
foreach (int s in r.AllowedIDs)
{
args.Player.SendMessage(r.RegionName + ": " + s);
args.Player.SendMessage(r.Name + ": " + s);
}
}
}
@ -1673,7 +1858,7 @@ namespace TShockAPI
var nameslist = new List<string>();
for (int i = 0; i < pagelimit && i + (page * pagelimit) < regions.Count; i++)
{
nameslist.Add(regions[i].RegionName);
nameslist.Add(regions[i].Name);
}
//convert the list to an array for joining
@ -1918,8 +2103,8 @@ namespace TShockAPI
else
{
var ply = players[0];
args.Player.SendMessage("Annoying " + ply.Name + " for " + annoy.ToString() + " seconds.");
(new Thread(new ParameterizedThreadStart(ply.Whoopie))).Start(annoy);
args.Player.SendMessage("Annoying " + ply.Name + " for " + annoy + " seconds.");
(new Thread(ply.Whoopie)).Start(annoy);
}
}
#endregion General Commands
@ -2010,7 +2195,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.SendMessage(string.Format("Gave {0} {1}(s).", itemAmount.ToString(), item.name));
args.Player.SendMessage(string.Format("Gave {0} {1}(s).", itemAmount, item.name));
}
else
{
@ -2080,8 +2265,8 @@ namespace TShockAPI
if (itemAmount == 0 || itemAmount > item.maxStack)
itemAmount = item.maxStack;
plr.GiveItem(item.type, item.name, item.width, item.height, itemAmount);
args.Player.SendMessage(string.Format("Gave {0} {1} {2}(s).", plr.Name, itemAmount.ToString(), item.name));
plr.SendMessage(string.Format("{0} gave you {1} {2}(s).", args.Player.Name, itemAmount.ToString(), item.name));
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));
}
else
{

View file

@ -27,9 +27,9 @@ namespace TShockAPI
public int DefaultMaximumSpawns = 4;
public int DefaultSpawnRate = 700;
public int ServerPort = 7777;
public bool EnableWhitelist = false;
public bool InfiniteInvasion = false;
public bool AlwaysPvP = false;
public bool EnableWhitelist;
public bool InfiniteInvasion;
public bool AlwaysPvP;
public bool KickCheaters = true;
public bool BanCheaters = true;
public bool KickGriefers = true;
@ -44,24 +44,24 @@ namespace TShockAPI
public string DistributationAgent = "facepunch";
public int MaxSlots = 8;
public bool RangeChecks = true;
public bool SpamChecks = false;
public bool DisableBuild = false;
public bool SpamChecks;
public bool DisableBuild;
public int TileThreshold = 60;
public float[] AdminChatRGB = { 255, 0, 0 };
public float[] SuperAdminChatRGB = { 255, 0, 0 };
public string AdminChatPrefix = "(Admin) ";
public bool AdminChatEnabled = true;
public int PvpThrottle = 0;
public int PvpThrottle;
public int BackupInterval = 0;
public int BackupInterval;
public int BackupKeepFor = 60;
public bool RememberLeavePos = false;
public bool RememberLeavePos;
public bool HardcoreOnly = false;
public bool KickOnHardcoreDeath = false;
public bool BanOnHardcoreDeath = false;
public bool HardcoreOnly;
public bool KickOnHardcoreDeath;
public bool BanOnHardcoreDeath;
public bool AutoSave = true;
@ -93,12 +93,25 @@ namespace TShockAPI
public string TileKillAbuseReason = "Tile Kill abuse ({0})";
public string HardcoreBanReason = "Death results in a ban";
public string HardcoreKickReason = "Death results in a kick";
public string ProjectileAbuseReason = "Projectile abuse";
public bool EnableDNSHostResolution = false;
public bool EnableDNSHostResolution;
public bool EnableBanOnUsernames = false;
public bool EnableBanOnUsernames;
public bool EnableAntiLag = true;
public string DefaultRegistrationGroupName = "default";
public bool DisableSpewLogs = true;
/// <summary>
/// Valid types are "sha512", "sha256", "md5"
/// </summary>
public string HashAlgorithm = "sha512";
public bool BufferPackets = false;
public static ConfigFile Read(string path)
{
if (!File.Exists(path))

View file

@ -1,4 +1,4 @@
/*
/*
TShock, a server mod for Terraria
Copyright (C) 2011 The TShock Team
@ -17,12 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using Community.CsharpSqlite.SQLiteClient;
using TShockAPI.DB;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
@ -34,18 +31,15 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'Bans' ('IP' TEXT PRIMARY KEY, 'Name' TEXT, 'Reason' TEXT);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS Bans (IP VARCHAR(255) PRIMARY, Name VARCHAR(255), Reason VARCHAR(255));";
var table = new SqlTable("Bans",
new SqlColumn("IP", MySqlDbType.String, 16) { Primary = true },
new SqlColumn("Name", MySqlDbType.Text),
new SqlColumn("Reason", MySqlDbType.Text)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
com.ExecuteNonQuery();
String file = Path.Combine( TShock.SavePath, "bans.txt" );
String file = Path.Combine(TShock.SavePath, "bans.txt");
if (File.Exists(file))
{
using (StreamReader sr = new StreamReader(file))
@ -54,43 +48,32 @@ namespace TShockAPI.DB
while ((line = sr.ReadLine()) != null)
{
String[] info = line.Split('|');
string query;
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO Bans (IP, Name, Reason) VALUES (@ip, @name, @reason);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO Bans SET IP=@ip, Name=@name, Reason=@reason;";
com.AddParameter("@ip", info[0].Trim());
com.AddParameter("@name", info[1].Trim());
com.AddParameter("@reason", info[2].Trim());
com.ExecuteNonQuery();
com.Parameters.Clear();
query = "INSERT OR IGNORE INTO Bans (IP, Name, Reason) VALUES (@0, @1, @2);";
else
query = "INSERT IGNORE INTO Bans SET IP=@0, Name=@1, Reason=@2;";
db.Query(query, info[0].Trim(), info[1].Trim(), info[2].Trim());
}
}
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "bans.txt");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
File.Move(file, file2);
}
}
}
public Ban GetBanByIp(string ip)
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Bans WHERE IP=@ip";
com.AddParameter("@ip", ip);
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
{
if (reader.Read())
return new Ban((string)reader["IP"], (string)reader["Name"], (string)reader["Reason"]);
reader.Close();
}
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"));
}
}
catch (Exception ex)
@ -107,21 +90,15 @@ namespace TShockAPI.DB
return null;
}
try
{
using (var com = database.CreateCommand())
{
var namecol = casesensitive ? "Name" : "UPPER(Name)";
if (!casesensitive)
name = name.ToUpper();
com.CommandText = "SELECT * FROM Bans WHERE " + namecol + "=@name";
com.AddParameter("@name", name);
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
{
if (reader.Read())
return new Ban((string)reader["IP"], (string)reader["Name"], (string)reader["Reason"]);
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("Reason"));
reader.Close();
}
}
}
catch (Exception ex)
@ -135,15 +112,7 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "INSERT INTO Bans (IP, Name, Reason) VALUES (@ip, @name, @reason);";
com.AddParameter("@ip", ip);
com.AddParameter("@name", name);
com.AddParameter("@reason", reason);
com.ExecuteNonQuery();
}
return true;
return database.Query("INSERT INTO Bans (IP, Name, Reason) VALUES (@0, @1, @2);", ip, name, reason) != 0;
}
catch (Exception ex)
{
@ -156,13 +125,7 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "DELETE FROM Bans WHERE IP=@ip";
com.AddParameter("@ip", ip);
com.ExecuteNonQuery();
return true;
}
return database.Query("DELETE FROM Bans WHERE IP=@0", ip) != 0;
}
catch (Exception ex)
{
@ -174,12 +137,7 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "DELETE FROM Bans";
com.ExecuteNonQuery();
return true;
}
return database.Query("DELETE FROM Bans") != 0;
}
catch (Exception ex)
{

View file

@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace TShockAPI.DB
{
public static class DbExt
{
public static IDbDataParameter AddParameter(this IDbCommand command, string name, object data)
{
var parm = command.CreateParameter();
parm.ParameterName = name;
parm.Value = data;
command.Parameters.Add(parm);
return parm;
}
static Dictionary<Type, Func<IDataReader, int, object>> ReadFuncs = new Dictionary<Type, Func<IDataReader, int, object>>()
{
{typeof(bool), (s, i) => s.GetBoolean(i)},
{typeof(byte), (s, i) => s.GetByte(i)},
{typeof(Int16), (s, i) => s.GetInt16(i)},
{typeof(Int32), (s, i) => s.GetInt32(i)},
{typeof(Int64), (s, i) => s.GetInt64(i)},
{typeof(string), (s, i) => s.GetString(i)},
{typeof(decimal), (s, i) => s.GetDecimal(i)},
{typeof(float), (s, i) => s.GetFloat(i)},
{typeof(double), (s, i) => s.GetDouble(i)},
};
public static T Get<T>(this IDataReader reader, string column)
{
return reader.Get<T>(reader.GetOrdinal(column));
}
public static T Get<T>(this IDataReader reader, int column)
{
if (ReadFuncs.ContainsKey(typeof(T)))
return (T)ReadFuncs[typeof(T)](reader, column);
throw new NotImplementedException();
}
}
}

View file

@ -1,10 +1,9 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Community.CsharpSqlite.SQLiteClient;
using System.IO;
using System.Linq;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
@ -18,17 +17,13 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'GroupList' ('GroupName' TEXT PRIMARY KEY, 'Commands' TEXT, 'OrderBy' TEXT);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS GroupList (GroupName VARCHAR(255) PRIMARY, Commands VARCHAR(255), OrderBy VARCHAR(255));";
com.ExecuteNonQuery();
}
var table = new SqlTable("GroupList",
new SqlColumn("GroupName", MySqlDbType.VarChar, 32) { Primary = true },
new SqlColumn("Commands", MySqlDbType.Text),
new SqlColumn("ChatColor", MySqlDbType.Text)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
//Add default groups
AddGroup("trustedadmin", "admin,maintenance,cfg,butcher,item,heal,immunetoban,ignorecheatdetection,ignoregriefdetection,usebanneditem,manageusers");
@ -50,35 +45,28 @@ namespace TShockAPI.DB
String[] info = line.Split(' ');
String comms = "";
int size = info.Length;
int test = 0;
bool hasOrder = int.TryParse(info[info.Length - 1], out test);
if (hasOrder)
size = info.Length - 1;
for (int i = 1; i < size; i++)
{
if (!comms.Equals(""))
comms = comms + ",";
comms = comms + info[i].Trim();
}
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO GroupList (GroupName, Commands, OrderBy) VALUES (@groupname, @commands, @order);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO GroupList SET GroupName=@groupname, Commands=@commands, OrderBy=@order;";
com.AddParameter("@groupname", info[0].Trim());
com.AddParameter("@commands", comms);
com.AddParameter("@order", hasOrder ? info[info.Length - 1] : "0");
com.ExecuteNonQuery();
}
string query = "";
if (TShock.Config.StorageType.ToLower() == "sqlite")
query = "INSERT OR IGNORE INTO GroupList (GroupName, Commands) VALUES (@0, @1);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
query = "INSERT IGNORE INTO GroupList SET GroupName=@0, Commands=@1;";
db.Query(query, info[0].Trim(), comms);
}
}
}
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "groups.txt");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
File.Move(file, file2);
@ -86,27 +74,6 @@ namespace TShockAPI.DB
}
/// <summary>
/// Adds group with name and permissions if it does not exist.
/// </summary>
/// <param name="name">name of group</param>
/// <param name="commands">permissions</param>
public void AddGroup(string name, string commands)
{
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"INSERT OR IGNORE INTO GroupList (GroupName, Commands, OrderBy) VALUES (@groupname, @commands, @order);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"INSERT IGNORE INTO GroupList SET GroupName=@groupname, Commands=@commands, OrderBy=@order;";
com.AddParameter("@groupname", name);
com.AddParameter("@commands", commands);
com.AddParameter("@order", "0");
com.ExecuteNonQuery();
}
}
public bool GroupExists(string group)
{
@ -123,93 +90,72 @@ namespace TShockAPI.DB
return false;
}
public String addGroup(String name, String permissions)
/// <summary>
/// Adds group with name and permissions if it does not exist.
/// </summary>
/// <param name="name">name of group</param>
/// <param name="permissions">permissions</param>
public String AddGroup(String name, String permissions, String ChatColor = "255,255,255")
{
String message = "";
if( GroupExists( name ) )
if (GroupExists(name))
return "Error: Group already exists. Use /modGroup to change permissions.";
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO GroupList (GroupName, Commands, OrderBy) VALUES (@groupname, @commands, @order);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO GroupList SET GroupName=@groupname, Commands=@commands, OrderBy=@order;";
com.AddParameter("@groupname", name);
com.AddParameter("@commands", permissions);
com.AddParameter("@order", "0");
if (com.ExecuteNonQuery() == 1)
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO GroupList (GroupName, Commands, ChatColor) VALUES (@0, @1, @2);" :
"INSERT IGNORE INTO GroupList SET GroupName=@0, Commands=@1";
if (database.Query(query, name, permissions, ChatColor) == 1)
message = "Group " + name + " has been created successfully.";
Group g = new Group(name);
Group g = new Group(name, null, ChatColor);
g.permissions.Add(permissions);
groups.Add(g);
}
return message;
}
public String delGroup(String name)
public String DeleteGroup(String name)
{
String message = "";
if (!GroupExists(name))
return "Error: Group doesn't exists.";
using (var com = database.CreateCommand())
{
com.CommandText = "Delete FROM GroupList WHERE GroupName=@groupname;";
com.AddParameter("@groupname", name);
if (com.ExecuteNonQuery() == 1)
if (database.Query("DELETE FROM GroupList WHERE GroupName=@0", name) == 1)
message = "Group " + name + " has been deleted successfully.";
groups.Remove(Tools.GetGroup(name));
}
return message;
}
public String addPermission(String name, List<String> permissions)
public String AddPermissions(String name, List<String> permissions)
{
String message = "";
if (!GroupExists(name))
return "Error: Group doesn't exists.";
using (var com = database.CreateCommand())
{
Group g = Tools.GetGroup(name);
List<String> perm = g.permissions;
foreach (String p in permissions)
{
if (!perm.Contains(p))
{
if (perm.Count > 0 && perm[0].Equals(""))
perm[0] = p;
else
g.permissions.Add(p);
}
}
com.CommandText = "UPDATE GroupList SET Commands=@perm WHERE GroupName=@name;";
com.AddParameter("@perm", String.Join(",", perm));
com.AddParameter("@name", name);
if (com.ExecuteNonQuery() == 1)
var group = Tools.GetGroup(name);
//Add existing permissions (without duplicating)
permissions.AddRange(group.permissions.Where(s => !permissions.Contains(s)));
if (database.Query("UPDATE GroupList SET Commands=@0 WHERE GroupName=@1", String.Join(",", permissions), name) != 0)
message = "Group " + name + " has been modified successfully.";
}
return message;
}
public String delPermission(String name, List<String> permissions)
public String DeletePermissions(String name, List<String> permissions)
{
String message = "";
if (!GroupExists(name))
return "Error: Group doesn't exists.";
using (var com = database.CreateCommand())
{
Group g = Tools.GetGroup(name);
List<String> perm = g.permissions;
foreach (String p in permissions)
{
if (perm.Contains(p))
g.permissions.Remove(p);
}
com.CommandText = "UPDATE GroupList SET Commands=@perm WHERE GroupName=@name;";
com.AddParameter("@perm", String.Join(",", perm));
com.AddParameter("@name", name);
if (com.ExecuteNonQuery() == 1)
var group = Tools.GetGroup(name);
//Only get permissions that exist in the group.
var newperms = permissions.Where(s => group.permissions.Contains(s));
if (database.Query("UPDATE GroupList SET Commands=@0 WHERE GroupName=@1", String.Join(",", newperms), name) != 0)
message = "Group " + name + " has been modified successfully.";
}
return message;
}
@ -220,10 +166,7 @@ namespace TShockAPI.DB
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Grouplist;";
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Grouplist"))
{
while (reader.Read())
{
@ -237,25 +180,16 @@ namespace TShockAPI.DB
{
group.AddPermission(commands[i].Trim());
}
String[] chatcolour = (reader.Get<String>("ChatColor") ?? "").Split(',');
if (chatcolour.Length == 3)
{
byte.TryParse(chatcolour[0], out group.R);
byte.TryParse(chatcolour[1], out group.G);
byte.TryParse(chatcolour[2], out group.B);
}
groups.Add(group);
}
}
/** ORDER BY IS DUMB
//Inherit all commands from group below in order, unless Order is 0 (unique groups anyone)
foreach (Group group in groups)
{
if (group.Order != 0 && group.Order < groups.Count)
{
for (int i = group.Order + 1; i < groups.Count; i++)
{
for (int j = 0; j < groups[i].permissions.Count; j++)
{
group.AddPermission(groups[i].permissions[j]);
}
}
}
}*/
}
}
catch (Exception ex)
{

View file

@ -0,0 +1,256 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using TShockAPI.Extensions;
namespace TShockAPI.DB
{
public interface IQueryBuilder
{
string CreateTable(SqlTable table);
string AlterTable(SqlTable from, SqlTable to);
string DbTypeToString(MySqlDbType type, int? length);
string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres);
string InsertValues(string table, List<SqlValue> values);
string ReadColumn(string table, List<SqlValue> wheres);
}
public class SqliteQueryCreator : IQueryBuilder
{
public string CreateTable(SqlTable table)
{
var columns = table.Columns.Select(c => "'{0}' {1} {2} {3} {4}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "", c.AutoIncrement ? "AUTOINCREMENT" : "", c.NotNull ? "NOT NULL" : "", c.Unique ? "UNIQUE" : ""));
return "CREATE TABLE '{0}' ({1})".SFormat(table.Name, string.Join(", ", columns));
}
static Random rand = new Random();
/// <summary>
/// Alter a table from source to destination
/// </summary>
/// <param name="from">Must have name and column names. Column types are not required</param>
/// <param name="to">Must have column names and column types.</param>
/// <returns></returns>
public string AlterTable(SqlTable from, SqlTable to)
{
var rstr = rand.NextString(20);
var alter = "ALTER TABLE '{0}' RENAME TO '{1}_{0}'".SFormat(from.Name, rstr);
var create = CreateTable(to);
//combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
//exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
var insert = "INSERT INTO '{0}' ({1}) SELECT {1} FROM {2}_{0}".SFormat(from.Name, string.Join(", ", from.Columns.Where(c => to.Columns.Any(c2 => c2.Name == c.Name)).Select(c => c.Name)), rstr);
var drop = "DROP TABLE '{0}_{1}'".SFormat(rstr, from.Name);
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
/*
ALTER TABLE "main"."Bans" RENAME TO "oXHFcGcd04oXHFcGcd04_Bans"
CREATE TABLE "main"."Bans" ("IP" TEXT PRIMARY KEY ,"Name" TEXT)
INSERT INTO "main"."Bans" SELECT "IP","Name" FROM "main"."oXHFcGcd04oXHFcGcd04_Bans"
DROP TABLE "main"."oXHFcGcd04oXHFcGcd04_Bans"
*
* Twitchy - Oh. I get it!
*/
}
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
{
var sbvalues = new StringBuilder();
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Name + "=" + value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append(",");
count++;
}
count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value.ToString());
if (count != wheres.Count - 1)
sbvalues.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "UPDATE '{0}' SET {1} WHERE {2}".SFormat(table, sbvalues.ToString(), sbwheres.ToString());
else
return "UPDATE '{0}' SET {1}".SFormat(table, sbvalues.ToString());
}
public string InsertValues(string table, List<SqlValue> values)
{
var sbnames = new StringBuilder();
var sbvalues = new StringBuilder();
int count = 0;
foreach (SqlValue name in values)
{
sbnames.Append(name.Name);
if (count != values.Count - 1)
sbnames.Append(", ");
count++;
}
count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append(", ");
count++;
}
return "INSERT INTO '{0}' ({1}) VALUES ({2})".SFormat(table, sbnames.ToString(), sbvalues.ToString());
}
public string ReadColumn(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value.ToString());
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if(wheres.Count > 0)
return "SELECT * FROM {0} WHERE {1}".SFormat(table, sbwheres.ToString());
else
return "SELECT * FROM {0}".SFormat(table);
}
static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
{
{MySqlDbType.VarChar, "TEXT"},
{MySqlDbType.String, "TEXT"},
{MySqlDbType.Text, "TEXT"},
{MySqlDbType.TinyText, "TEXT"},
{MySqlDbType.MediumText, "TEXT"},
{MySqlDbType.LongText, "TEXT"},
{MySqlDbType.Int32, "INTEGER"},
};
public string DbTypeToString(MySqlDbType type, int? length)
{
string ret;
if (TypesAsStrings.TryGetValue(type, out ret))
return ret;
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
}
}
public class MysqlQueryCreator : IQueryBuilder
{
public string CreateTable(SqlTable table)
{
var columns = table.Columns.Select(c => "{0} {1} {2} {3}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "", c.AutoIncrement ? "AUTOINCREMENT" : "", c.NotNull ? "NOT NULL" : ""));
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
return "CREATE TABLE {0} ({1}) {2}".SFormat(table.Name, string.Join(", ", columns), uniques.Count() > 0 ? ", UNIQUE({0})".SFormat(string.Join(", ", uniques)) : "");
}
static Random rand = new Random();
/// <summary>
/// Alter a table from source to destination
/// </summary>
/// <param name="from">Must have name and column names. Column types are not required</param>
/// <param name="to">Must have column names and column types.</param>
/// <returns></returns>
public string AlterTable(SqlTable from, SqlTable to)
{
var rstr = rand.NextString(20);
var alter = "RENAME TABLE {0} TO {1}_{0}".SFormat(from.Name, rstr);
var create = CreateTable(to);
//combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
//exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
var insert = "INSERT INTO {0} ({1}) SELECT {1} FROM {2}_{0}".SFormat(from.Name, string.Join(", ", from.Columns.Where(c => to.Columns.Any(c2 => c2.Name == c.Name)).Select(c => c.Name)), rstr);
var drop = "DROP TABLE {0}_{1}".SFormat(rstr, from.Name);
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
}
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
{
var sbvalues = new StringBuilder();
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Name + "=" + value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append("AND");
count++;
}
count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value.ToString());
if (count != wheres.Count - 1)
sbvalues.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "UPDATE {0} SET {1} WHERE {2}".SFormat(table, sbvalues.ToString(), sbwheres.ToString());
else
return "UPDATE {0} SET {1}".SFormat(table, sbvalues.ToString());
}
public string InsertValues(string table, List<SqlValue> values)
{
var sbnames = new StringBuilder();
var sbvalues = new StringBuilder();
int count = 0;
foreach (SqlValue name in values)
{
sbnames.Append(name.Name);
if (count != values.Count - 1)
sbnames.Append(", ");
count++;
}
count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append(", ");
count++;
}
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(table, sbnames.ToString(), sbvalues.ToString());
}
public string ReadColumn(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value.ToString());
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "SELECT * FROM {0} WHERE {1}".SFormat(table, sbwheres.ToString());
else
return "SELECT * FROM {0}".SFormat(table);
}
static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
{
{MySqlDbType.VarChar, "VARCHAR"},
{MySqlDbType.String, "CHAR"},
{MySqlDbType.Text, "TEXT"},
{MySqlDbType.TinyText, "TINYTEXT"},
{MySqlDbType.MediumText, "MEDIUMTEXT"},
{MySqlDbType.LongText, "LONGTEXT"},
{MySqlDbType.Int32, "INT"},
};
public string DbTypeToString(MySqlDbType type, int? length)
{
string ret;
if (TypesAsStrings.TryGetValue(type, out ret))
return ret + (length != null ? "({0})".SFormat((int)length) : "");
throw new NotImplementedException(Enum.GetName(typeof(MySqlDbType), type));
}
}
}

View file

@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Community.CsharpSqlite.SQLiteClient;
using TShockAPI.DB;
using System.IO;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
@ -18,15 +15,11 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'ItemBans' ('ItemName' TEXT PRIMARY KEY);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS ItemBans (ItemName VARCHAR(255) PRIMARY);";
com.ExecuteNonQuery();
var table = new SqlTable("ItemBans",
new SqlColumn("ItemName", MySqlDbType.VarChar, 50) { Primary = true }
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
String file = Path.Combine(TShock.SavePath, "itembans.txt");
if (File.Exists(file))
@ -38,16 +31,15 @@ namespace TShockAPI.DB
{
if (!line.Equals("") && !line.Substring(0, 1).Equals("#"))
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO 'ItemBans' (ItemName) VALUES (@name);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO ItemBans SET ItemName=@name;";
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO 'ItemBans' (ItemName) VALUES (@0);" :
"INSERT IGNORE INTO ItemBans SET ItemName=@0;";
int id = 0;
int.TryParse(line, out id);
com.AddParameter("@name", Tools.GetItemById(id).name);
com.ExecuteNonQuery();
com.Parameters.Clear();
database.Query(query, Tools.GetItemById(id).name);
}
}
}
@ -55,12 +47,11 @@ namespace TShockAPI.DB
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "itembans.txt");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
File.Move(file, file2);
}
}
UpdateItemBans();
}
@ -68,30 +59,21 @@ namespace TShockAPI.DB
public void UpdateItemBans()
{
ItemBans.Clear();
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM ItemBans";
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM ItemBans"))
{
while (reader!=null&&reader.Read())
while (reader != null && reader.Read())
ItemBans.Add(reader.Get<string>("ItemName"));
}
}
}
public void AddNewBan(string itemname = "")
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "INSERT INTO ItemBans (ItemName) VALUES (@itemname);";
com.AddParameter("@itemname", Tools.GetItemByName(itemname)[0].name);
com.ExecuteNonQuery();
if( !ItemIsBanned( itemname ) )
database.Query("INSERT INTO ItemBans (ItemName) VALUES (@0);", Tools.GetItemByName(itemname)[0].name);
if (!ItemIsBanned(itemname))
ItemBans.Add(itemname);
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -104,14 +86,9 @@ namespace TShockAPI.DB
return;
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "Delete FROM 'ItemBans' WHERE ItemName=@itemname;";
com.AddParameter("@itemname", Tools.GetItemByName(itemname)[0].name);
com.ExecuteNonQuery();
database.Query("Delete FROM 'ItemBans' WHERE ItemName=@0;", Tools.GetItemByName(itemname)[0].name);
ItemBans.Remove(itemname);
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());

View file

@ -1,4 +1,4 @@
/*
/*
TShock, a server mod for Terraria
Copyright (C) 2011 The TShock Team
@ -18,17 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Data;
using TShockAPI.DB;
using Community.CsharpSqlite.SQLiteClient;
using System.IO;
using System.Xml;
using Microsoft.Xna.Framework;
using MySql.Data.MySqlClient;
using Terraria;
namespace TShockAPI.DB
{
public class RegionManager
@ -41,187 +37,120 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
var table = new SqlTable("Regions",
new SqlColumn("X1", MySqlDbType.Int32),
new SqlColumn("Y1", MySqlDbType.Int32),
new SqlColumn("height", MySqlDbType.Int32),
new SqlColumn("width", MySqlDbType.Int32),
new SqlColumn("RegionName", MySqlDbType.VarChar, 50) { Primary = true },
new SqlColumn("WorldID", MySqlDbType.Text),
new SqlColumn("UserIds", MySqlDbType.Text),
new SqlColumn("Protected", MySqlDbType.Int32)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
ImportOld();
}
public void ImportOld()
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'Regions' ('X1' NUMERIC, 'Y1' NUMERIC, 'height' NUMERIC, 'width' NUMERIC, 'RegionName' TEXT PRIMARY KEY, 'WorldID' TEXT, 'UserIds' TEXT, 'Protected' NUMERIC);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS Regions (X1 INT(11), Y1 INT(11), height INT(11), width INT(11), RegionName VARCHAR(255) PRIMARY, WorldID VARCHAR(255), UserIds VARCHAR(255), Protected INT(1));";
com.ExecuteNonQuery();
String file = Path.Combine(TShock.SavePath, "regions.xml");
String name = "";
String world = "";
int x1 = 0;
int x2 = 0;
int y1 = 0;
int y2 = 0;
int prot = 0;
int users = 0;
String[] ips;
String ipstr = "";
int updates = 0;
if (File.Exists(file))
if (!File.Exists(file))
return;
Region region;
Rectangle rect;
using (var sr = new StreamReader(file))
{
using (var reader = XmlReader.Create(sr))
{
XmlReader reader;
reader = XmlReader.Create(new StreamReader(file));
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
if (reader.NodeType != XmlNodeType.Element || reader.Name != "ProtectedRegion")
continue;
region = new Region();
rect = new Rectangle();
bool endregion = false;
while (reader.Read() && !endregion)
{
case XmlNodeType.Element:
switch (reader.Name)
if (reader.NodeType != XmlNodeType.Element)
continue;
string name = reader.Name;
while (reader.Read() && reader.NodeType != XmlNodeType.Text) ;
switch (name)
{
case "ProtectedRegion":
name = "";
world = "";
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
prot = 0;
users = 0;
ips = null;
ipstr = "";
break;
case "RegionName":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
name = reader.Value;
region.Name = reader.Value;
break;
case "Point1X":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
int.TryParse(reader.Value, out x1);
int.TryParse(reader.Value, out rect.X);
break;
case "Point1Y":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
int.TryParse(reader.Value, out y1);
int.TryParse(reader.Value, out rect.Y);
break;
case "Point2X":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
int.TryParse(reader.Value, out x2);
int.TryParse(reader.Value, out rect.Width);
break;
case "Point2Y":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
int.TryParse(reader.Value, out y2);
int.TryParse(reader.Value, out rect.Height);
break;
case "Protected":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
if (reader.Value.Equals("True"))
{
prot = 0;
}
else
{
prot = 1;
}
region.DisableBuild = reader.Value.ToLower().Equals("true");
break;
case "WorldName":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
world = reader.Value;
region.WorldID = reader.Value;
break;
case "AllowedUserCount":
while (reader.NodeType != XmlNodeType.Text)
reader.Read();
int.TryParse(reader.Value, out users);
if (users > 0)
{
ips = new String[users];
for (int i = 0; i < users; i++)
{
do
reader.Read();
while (reader.NodeType != XmlNodeType.Text);
ips[i] = reader.Value;
break;
case "IP":
region.AllowedIDs.Add(int.Parse(reader.Value));
break;
default:
endregion = true;
break;
}
ipstr = "";
for (int i = 0; i < ips.Length; i++)
{
try
{
if (ipstr != "")
ipstr += ",";
ipstr += TShock.Users.GetUserID(ips[i]);
}
catch (Exception)
{
Log.Error("An IP address failed to import. It wasn't a user in the new user system.");
}
}
region.Area = rect;
using (var com = database.CreateCommand())
{
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO Regions VALUES (@0, @1, @2, @3, @4, @5, @6, @7);" :
"INSERT IGNORE INTO Regions SET X1=@0, Y1=@1, height=@2, width=@3, RegionName=@4, WorldID=@5, UserIds=@6, Protected=@7;";
database.Query(query, region.Area.X, region.Area.Y, region.Area.Width, region.Area.Height, region.Name, region.WorldID, "", region.DisableBuild);
}
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO Regions VALUES (@tx, @ty, @height, @width, @name, @worldid, @userids, @protected);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO Regions SET X1=@tx, Y1=@ty, height=@height, width=@width, RegionName=@name, WorldID=@world, UserIds=@userids, Protected=@protected;";
com.AddParameter("@tx", x1);
com.AddParameter("@ty", y1);
com.AddParameter("@width", x2);
com.AddParameter("@height", y2);
com.AddParameter("@name", name);
com.AddParameter("@worldid", world);
com.AddParameter("@userids", ipstr);
com.AddParameter("@protected", prot);
updates += com.ExecuteNonQuery();
com.Parameters.Clear();
break;
}
break;
case XmlNodeType.Text:
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
break;
case XmlNodeType.Comment:
break;
case XmlNodeType.EndElement:
break;
//Todo: What should this be? We don't really have a way to go from ips to userids
/*string.Join(",", region.AllowedIDs)*/
}
}
}
}
reader.Close();
reader = null;
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "regions.xml");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
//File.Move(file, file2);
}
if (updates > 0)
File.Move(file, file2);
ReloadAllRegions();
}
}
public void ConvertDB()
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "UPDATE Regions SET WorldID=@worldid";
com.AddParameter("@worldid", Main.worldID.ToString());
com.ExecuteNonQuery();
com.Parameters.Clear();
com.CommandText = "UPDATE Regions SET UserIds=@UserIds";
com.AddParameter("@UserIds", "");
com.ExecuteNonQuery();
database.Query("UPDATE Regions SET WorldID=@0, UserIds=''", Main.worldID.ToString());
ReloadAllRegions();
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -232,11 +161,7 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Regions WHERE WorldID=@worldid";
com.AddParameter("@worldid", Main.worldID.ToString());
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Regions WHERE WorldID=@0", Main.worldID.ToString()))
{
Regions.Clear();
while (reader.Read())
@ -246,23 +171,24 @@ namespace TShockAPI.DB
int height = reader.Get<int>("height");
int width = reader.Get<int>("width");
int Protected = reader.Get<int>("Protected");
string MergedIDs = DbExt.Get<string>(reader, "UserIds");
string name = DbExt.Get<string>(reader, "RegionName");
System.Console.WriteLine(MergedIDs);
string MergedIDs = reader.Get<string>("UserIds");
string name = reader.Get<string>("RegionName");
string[] SplitIDs = MergedIDs.Split(',');
Region r = new Region(new Rectangle(X1, Y1, width, height), name, Protected, Main.worldID.ToString());
r.RegionAllowedIDs = new int[SplitIDs.Length];
Region r = new Region(new Rectangle(X1, Y1, width, height), name, Protected != 0, Main.worldID.ToString());
try
{
for (int i = 0; i < SplitIDs.Length; i++)
{
if (SplitIDs.Length == 1 && SplitIDs[0].Equals(""))
{
break;
}
//System.Console.WriteLine(SplitIDs[i]);
r.RegionAllowedIDs[i] = Convert.ToInt32(SplitIDs[i]);
int id;
if (Int32.TryParse(SplitIDs[i], out id)) // if unparsable, it's not an int, so silently skip
r.AllowedIDs.Add(id);
else if (SplitIDs[i] == "") // Split gotcha, can return an empty string with certain conditions
// but we only want to let the user know if it's really a nonparsable integer.
Log.Warn("One of your UserIDs is not a usable integer: " + SplitIDs[i]);
}
}
catch (Exception e)
@ -275,8 +201,6 @@ namespace TShockAPI.DB
Regions.Add(r);
}
reader.Close();
}
}
}
catch (Exception ex)
@ -285,30 +209,59 @@ namespace TShockAPI.DB
}
}
public void ReloadForUnitTest(String n)
{
using (var reader = database.QueryReader("SELECT * FROM Regions WHERE WorldID=@0", n))
{
Regions.Clear();
while (reader.Read())
{
int X1 = reader.Get<int>("X1");
int Y1 = reader.Get<int>("Y1");
int height = reader.Get<int>("height");
int width = reader.Get<int>("width");
int Protected = reader.Get<int>("Protected");
string MergedIDs = reader.Get<string>("UserIds");
string name = reader.Get<string>("RegionName");
string[] SplitIDs = MergedIDs.Split(',');
Region r = new Region(new Rectangle(X1, Y1, width, height), name, Protected != 0, Main.worldID.ToString());
try
{
for (int i = 0; i < SplitIDs.Length; i++)
{
int id;
if (Int32.TryParse(SplitIDs[i], out id)) // if unparsable, it's not an int, so silently skip
r.AllowedIDs.Add(id);
else if (SplitIDs[i] == "") // Split gotcha, can return an empty string with certain conditions
// but we only want to let the user know if it's really a nonparsable integer.
Log.Warn("UnitTest: One of your UserIDs is not a usable integer: " + SplitIDs[i]);
}
}
catch (Exception e)
{
Log.Error("Your database contains invalid UserIDs (they should be ints).");
Log.Error("A lot of things will fail because of this. You must manually delete and re-create the allowed field.");
Log.Error(e.Message);
Log.Error(e.StackTrace);
}
Regions.Add(r);
}
}
}
public bool AddRegion(int tx, int ty, int width, int height, string regionname, string worldid)
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText =
"INSERT INTO Regions VALUES (@tx, @ty, @height, @width, @name, @worldid, @userids, @protected);";
com.AddParameter("@tx", tx);
com.AddParameter("@ty", ty);
com.AddParameter("@width", width);
com.AddParameter("@height", height);
com.AddParameter("@name", regionname.ToLower());
com.AddParameter("@worldid", worldid);
com.AddParameter("@userids", "");
com.AddParameter("@protected", 1);
if (com.ExecuteNonQuery() > 0)
{
Regions.Add(new Region(new Rectangle(tx, ty, width, height), regionname, 0, worldid));
database.Query("INSERT INTO Regions VALUES (@0, @1, @2, @3, @4, @5, @6, @7);", tx, ty, width, height, regionname, worldid, "", 1);
Regions.Add(new Region(new Rectangle(tx, ty, width, height), regionname, true, worldid));
return true;
}
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -320,16 +273,10 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "DELETE FROM Regions WHERE RegionName=@name AND WorldID=@worldid";
com.AddParameter("@name", name.ToLower());
com.AddParameter("@worldid", Main.worldID.ToString());
com.ExecuteNonQuery();
ReloadAllRegions();
database.Query("DELETE FROM Regions WHERE RegionName=@0 AND WorldID=@1", name, Main.worldID.ToString());
Regions.Remove(getRegion(name));
return true;
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -341,16 +288,24 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "UPDATE Regions SET Protected=@bool WHERE RegionName=@name AND WorldID=@worldid";
com.AddParameter("@name", name);
com.AddParameter("@bool", state ? 1 : 0);
com.AddParameter("@worldid", Main.worldID.ToString());
int q = com.ExecuteNonQuery();
ReloadAllRegions();
return (q > 0);
database.Query("UPDATE Regions SET Protected=@0 WHERE RegionName=@1 AND WorldID=@2", state ? 1 : 0, name, Main.worldID.ToString());
getRegion(name).DisableBuild = state;
return true;
}
catch (Exception ex)
{
Log.Error(ex.ToString());
return false;
}
}
public bool SetRegionStateTest(string name, string world, bool state)
{
try
{
database.Query("UPDATE Regions SET Protected=@0 WHERE RegionName=@1 AND WorldID=@2", state ? 1 : 0, name, world);
getRegion(name).DisableBuild = state;
return true;
}
catch (Exception ex)
{
@ -379,9 +334,9 @@ namespace TShockAPI.DB
{
foreach (Region region in Regions)
{
if (x >= region.RegionArea.Left && x <= region.RegionArea.Right &&
y >= region.RegionArea.Top && y <= region.RegionArea.Bottom &&
region.DisableBuild == 1)
if (x >= region.Area.Left && x <= region.Area.Right &&
y >= region.Area.Top && y <= region.Area.Bottom &&
region.DisableBuild)
{
return true;
}
@ -392,7 +347,7 @@ namespace TShockAPI.DB
public static List<string> ListIDs(string MergedIDs)
{
List<string> SplitIDs = new List<string>();
var sb = new StringBuilder();
/*var sb = new StringBuilder();
for (int i = 0; i < MergedIDs.Length; i++)
{
char c = MergedIDs[i];
@ -406,23 +361,22 @@ namespace TShockAPI.DB
SplitIDs.Add(sb.ToString());
sb.Clear();
}
}*/
String[] s = MergedIDs.Split(',');
for (int i = 0; i < s.Length; i++)
{
if (!s[i].Equals(""))
SplitIDs.Add(s[i]);
}
return SplitIDs;
}
public bool AddNewUser(string regionName, String userName)
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Regions WHERE RegionName=@name AND WorldID=@worldid";
com.AddParameter("@name", regionName);
com.AddParameter("@worldid", Main.worldID.ToString());
string MergedIDs = string.Empty;
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Regions WHERE RegionName=@0 AND WorldID=@1", regionName, Main.worldID.ToString()))
{
if (reader.Read())
MergedIDs = reader.Get<string>("UserIds");
@ -432,27 +386,18 @@ namespace TShockAPI.DB
MergedIDs = Convert.ToString(TShock.Users.GetUserID(userName));
else
MergedIDs = MergedIDs + "," + Convert.ToString(TShock.Users.GetUserID(userName));
com.Parameters.Clear();
com.CommandText = "UPDATE Regions SET UserIds=@ids WHERE RegionName=@name AND WorldID=@worldid";
com.AddParameter("@ids", MergedIDs);
com.AddParameter("@name", regionName);
com.AddParameter("@worldid", Main.worldID.ToString());
if (com.ExecuteNonQuery() > 0)
if (database.Query("UPDATE Regions SET UserIds=@0 WHERE RegionName=@1 AND WorldID=@2", MergedIDs, regionName, Main.worldID.ToString()) > 0)
{
ReloadAllRegions();
return true;
}
else
{
return false;
}
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
return false;
}
return false;
}
/// <summary>
@ -465,15 +410,10 @@ namespace TShockAPI.DB
var regions = new List<Region>();
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT RegionName FROM Regions WHERE WorldID=@worldid";
com.AddParameter("@worldid", worldid);
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT RegionName FROM Regions WHERE WorldID=@0", worldid))
{
while (reader.Read())
regions.Add(new Region { RegionName = reader.Get<string>("RegionName") });
}
regions.Add(new Region { Name = reader.Get<string>("RegionName") });
}
}
catch (Exception ex)
@ -482,35 +422,47 @@ namespace TShockAPI.DB
}
return regions;
}
public Region getRegion(String name)
{
foreach (Region r in Regions)
{
if (r.Name.Equals(name))
return r;
}
return new Region();
}
}
public class Region
{
public Rectangle RegionArea { get; set; }
public string RegionName { get; set; }
public int DisableBuild { get; set; }
public string RegionWorldID { get; set; }
public int[] RegionAllowedIDs { get; set; }
public Rectangle Area { get; set; }
public string Name { get; set; }
public bool DisableBuild { get; set; }
public string WorldID { get; set; }
public List<int> AllowedIDs { get; set; }
public Region(Rectangle region, string name, int disablebuild, string RegionWorldIDz)
public Region(Rectangle region, string name, bool disablebuild, string RegionWorldIDz)
: this()
{
RegionArea = region;
RegionName = name;
Area = region;
Name = name;
DisableBuild = disablebuild;
RegionWorldID = RegionWorldIDz;
WorldID = RegionWorldIDz;
}
public Region()
{
RegionArea = Rectangle.Empty;
RegionName = string.Empty;
DisableBuild = 1;
RegionWorldID = string.Empty;
Area = Rectangle.Empty;
Name = string.Empty;
DisableBuild = true;
WorldID = string.Empty;
AllowedIDs = new List<int>();
}
public bool InArea(Rectangle point)
{
if (RegionArea.Contains(point.X, point.Y))
if (Area.Contains(point.X, point.Y))
{
return true;
}
@ -528,14 +480,14 @@ namespace TShockAPI.DB
}
return false;
}
if (DisableBuild == 0)
if (!DisableBuild)
{
return true;
}
for (int i = 0; i < RegionAllowedIDs.Length; i++)
for (int i = 0; i < AllowedIDs.Count; i++)
{
if (RegionAllowedIDs[i] == ply.UserID)
if (AllowedIDs[i] == ply.UserID)
{
return true;
}

View file

@ -0,0 +1,94 @@
/*
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.Collections.Generic;
using System.Xml;
using System.Data;
using Microsoft.Xna.Framework;
using MySql.Data.MySqlClient;
using Terraria;
namespace TShockAPI.DB
{
public class RemeberedPosManager
{
public IDbConnection database;
public RemeberedPosManager(IDbConnection db)
{
database = db;
var table = new SqlTable("RememberedPos",
new SqlColumn("Name", MySqlDbType.VarChar, 50) { Primary = true },
new SqlColumn("IP", MySqlDbType.Text),
new SqlColumn("X", MySqlDbType.Int32),
new SqlColumn("Y", MySqlDbType.Int32),
new SqlColumn("WorldID", MySqlDbType.Text)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
}
public Vector2 GetLeavePos(string name, string IP)
{
try
{
using (var reader = database.QueryReader("SELECT * FROM RememberedPos WHERE Name=@0 AND IP=@1", name, IP))
{
if (reader.Read())
{
return new Vector2(reader.Get<int>("X"), reader.Get<int>("Y"));
}
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
return new Vector2();
}
public void InsertLeavePos(string name, string IP, int X, int Y)
{
if (GetLeavePos(name, IP) == Vector2.Zero)
{
try
{
database.Query("INSERT INTO RememberedPos (Name, IP, X, Y, WorldID) VALUES (@0, @1, @2, @3, @4);", name, IP, X, Y + 3, Main.worldID.ToString());
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
else
{
try
{
database.Query("UPDATE RememberedPos SET X = @0, Y = @1 WHERE Name = @2 AND IP = @3 AND WorldID = @4;", X, Y + 3, name, IP, Main.worldID.ToString());
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
}
}
}

35
TShockAPI/DB/SqlColumn.cs Normal file
View file

@ -0,0 +1,35 @@
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
public class SqlColumn
{
//Required
public string Name { get; set; }
public MySqlDbType Type { get; set; }
//Optional
public bool Unique { get; set; }
public bool Primary { get; set; }
public bool AutoIncrement { get; set; }
public bool NotNull { get; set; }
public string DefaultValue { get; set; }
/// <summary>
/// Length of the data type, null = default
/// </summary>
public int? Length { get; set; }
public SqlColumn(string name, MySqlDbType type)
: this(name, type, null)
{
}
public SqlColumn(string name, MySqlDbType type, int? length)
{
Name = name;
Type = type;
Length = length;
}
}
}

80
TShockAPI/DB/SqlTable.cs Normal file
View file

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
public class SqlTable
{
public List<SqlColumn> Columns { get; protected set; }
public string Name { get; protected set; }
public SqlTable(string name, params SqlColumn[] columns)
: this(name, new List<SqlColumn>(columns))
{
}
public SqlTable(string name, List<SqlColumn> columns)
{
Name = name;
Columns = columns;
}
}
public class SqlTableCreator
{
IDbConnection database;
IQueryBuilder creator;
public SqlTableCreator(IDbConnection db, IQueryBuilder provider)
{
database = db;
creator = provider;
}
public void EnsureExists(SqlTable table)
{
var columns = GetColumns(table);
if (columns.Count > 0)
{
if (!table.Columns.All(c => columns.Contains(c.Name)) || !columns.All(c => table.Columns.Any(c2 => c2.Name == c)))
{
var from = new SqlTable(table.Name, columns.Select(s => new SqlColumn(s, MySqlDbType.String)).ToList());
database.Query(creator.AlterTable(from, table));
}
}
else
{
database.Query(creator.CreateTable(table));
}
}
public List<string> GetColumns(SqlTable table)
{
var ret = new List<string>();
var name = database.GetSqlType();
if (name == SqlType.Sqlite)
{
using (var reader = database.QueryReader("PRAGMA table_info({0})".SFormat(table.Name)))
{
while (reader.Read())
ret.Add(reader.Get<string>("name"));
}
}
else if (name == SqlType.Mysql)
{
using (var reader = database.QueryReader("SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME=@0 AND TABLE_SCHEMA=@1", table.Name, database.Database))
{
while (reader.Read())
ret.Add(reader.Get<string>("COLUMN_NAME"));
}
}
else
{
throw new NotSupportedException();
}
return ret;
}
}
}

53
TShockAPI/DB/SqlValue.cs Normal file
View file

@ -0,0 +1,53 @@
using System.Data;
using MySql.Data.MySqlClient;
using System.Collections.Generic;
namespace TShockAPI.DB
{
public class SqlValue
{
public string Name { get; set; }
public object Value { get; set; }
public SqlValue(string name, object value)
{
Name = name;
Value = value;
}
}
public class SqlTableEditor
{
IDbConnection database;
IQueryBuilder creator;
public SqlTableEditor(IDbConnection db, IQueryBuilder provider)
{
database = db;
creator = provider;
}
public void UpdateValues(string table, List<SqlValue> values, List<SqlValue> wheres)
{
database.Query(creator.UpdateValue(table, values, wheres));
}
public void InsertValues(string table, List<SqlValue> values)
{
database.Query(creator.InsertValues(table, values));
}
public List<object> ReadColumn(string table, string column, List<SqlValue> wheres)
{
List<object> values = new List<object>();
using (var reader = database.QueryReader(creator.ReadColumn(table, wheres)))
{
while (reader.Read())
values.Add(reader.Reader.Get<object>(column));
}
return values;
}
}
}

View file

@ -18,12 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Community.CsharpSqlite.SQLiteClient;
using System.IO;
using MySql.Data.MySqlClient;
namespace TShockAPI.DB
{
public class UserManager
@ -34,16 +32,15 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'Users' ('ID' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, 'Username' VARCHAR(32) UNIQUE, 'Password' VARCHAR(64), 'Usergroup' TEXT, 'IP' VARCHAR(32));";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS Users (ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, Username VARCHAR(32) UNIQUE, Password VARCHAR(64), Usergroup VARCHAR(255), IP VARCHAR(15));";
com.ExecuteNonQuery();
var table = new SqlTable("Users",
new SqlColumn("ID", MySqlDbType.Int32) { Primary = true, AutoIncrement = true },
new SqlColumn("Username", MySqlDbType.VarChar, 32) { Unique = true },
new SqlColumn("Password", MySqlDbType.VarChar, 64),
new SqlColumn("Usergroup", MySqlDbType.Text),
new SqlColumn("IP", MySqlDbType.VarChar, 32)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
String file = Path.Combine(TShock.SavePath, "users.txt");
if (File.Exists(file))
@ -51,16 +48,11 @@ namespace TShockAPI.DB
using (StreamReader sr = new StreamReader(file))
{
String line;
while ((line = sr.ReadLine()) != null )
while ((line = sr.ReadLine()) != null)
{
if (line.Equals("") || line.Substring(0, 1).Equals("#") )
if (line.Equals("") || line.Substring(0, 1).Equals("#"))
continue;
String[] info = line.Split(' ');
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO Users (Username, Password, Usergroup, IP) VALUES (@name, @pass, @group, @ip);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO Users SET Username=@name, Password=@pass, Usergroup=@group, IP=@ip ;";
String username = "";
String sha = "";
String group = "";
@ -80,23 +72,23 @@ namespace TShockAPI.DB
sha = nameSha[1];
group = info[1];
}
com.AddParameter("@name", username.Trim());
com.AddParameter("@pass", sha.Trim());
com.AddParameter("@group", group.Trim());
com.AddParameter("@ip", ip.Trim());
com.ExecuteNonQuery();
com.Parameters.Clear();
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO Users (Username, Password, Usergroup, IP) VALUES (@0, @1, @2, @3)" :
"INSERT IGNORE INTO Users SET Username=@0, Password=@1, Usergroup=@2, IP=@3";
database.Query(query, username.Trim(), sha.Trim(), group.Trim(), ip.Trim());
}
}
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "users.txt");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
File.Move(file, file2);
}
}
}
/// <summary>
@ -107,25 +99,12 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@name, @password, @group, @ip);";
com.AddParameter("@name", user.Name);
com.AddParameter("@password", Tools.HashPassword(user.Password));
if (!TShock.Groups.GroupExists(user.Group))
throw new GroupNotExistsException(user.Group);
com.AddParameter("@group", user.Group);
com.AddParameter("@ip", user.Address);
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
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)
throw new UserExistsException(user.Name);
}
}
}
catch (Exception ex)
{
throw new UserManagerException("AddUser SQL returned an error", ex);
@ -140,26 +119,19 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
int affected = -1;
if (!string.IsNullOrEmpty(user.Address))
{
com.CommandText = "DELETE FROM Users WHERE IP=@ip";
com.AddParameter("@ip", user.Address);
affected = database.Query("DELETE FROM Users WHERE IP=@0", user.Address);
}
else
{
com.CommandText = "DELETE FROM Users WHERE Username=@name";
com.AddParameter("@name", user.Name);
affected = database.Query("DELETE FROM Users WHERE Username=@0", user.Name);
}
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
if (affected < 1)
throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address);
}
}
}
catch (Exception ex)
{
throw new UserManagerException("RemoveUser SQL returned an error", ex);
@ -176,18 +148,8 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "UPDATE Users SET Password = @password WHERE Username = @name;";
com.AddParameter("@name", user.Name);
com.AddParameter("@password", Tools.HashPassword(password));
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
throw new UserExistsException(user.Name);
}
}
if (database.Query("UPDATE Users SET Password = @0 WHERE Username = @1;", Tools.HashPassword(password), user.Name) == 0)
throw new UserNotExistException(user.Name);
}
catch (Exception ex)
{
@ -204,22 +166,11 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "UPDATE Users SET UserGroup = @group WHERE Username = @name;";
com.AddParameter("@name", user.Name);
if (!TShock.Groups.GroupExists(group))
throw new GroupNotExistsException(group);
com.AddParameter("@group", group);
using (var reader = com.ExecuteReader())
{
if (reader.RecordsAffected < 1)
throw new UserExistsException(user.Name);
}
}
if (database.Query("UPDATE Users SET UserGroup = @0 WHERE Username = @1;", group, user.Name) == 0)
throw new UserNotExistException(user.Name);
}
catch (Exception ex)
{
@ -238,12 +189,7 @@ namespace TShockAPI.DB
string[] returndata = new string[2];
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Users WHERE Username=@name";
com.AddParameter("@name", username.ToLower());
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Users WHERE Username=@0", username))
{
if (reader.Read())
{
@ -251,13 +197,11 @@ namespace TShockAPI.DB
returndata[1] = reader.Get<string>("UserGroup");
return returndata;
}
reader.Close();
}
}
}
catch (Exception ex)
{
Log.ConsoleError("FetchHashedPasswordAndGroup SQL returned an error: " + ex.ToString());
Log.ConsoleError("FetchHashedPasswordAndGroup SQL returned an error: " + ex);
}
return returndata;
}
@ -266,24 +210,17 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Users WHERE Username=@name";
com.AddParameter("@name", username.ToLower());
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Users WHERE Username=@0", username))
{
if (reader.Read())
{
return reader.Get<int>("ID");
}
reader.Close();
}
}
}
catch (Exception ex)
{
Log.ConsoleError("FetchHashedPasswordAndGroup SQL returned an error: " + ex.ToString());
Log.ConsoleError("FetchHashedPasswordAndGroup SQL returned an error: " + ex);
}
return -1;
}
@ -296,12 +233,7 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Users WHERE IP=@ip";
com.AddParameter("@ip", ip);
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Users WHERE IP=@0", ip))
{
if (reader.Read())
{
@ -310,10 +242,9 @@ namespace TShockAPI.DB
}
}
}
}
catch (Exception ex)
{
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex.ToString());
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex);
}
return Tools.GetGroup("default");
}
@ -322,26 +253,20 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
using (var reader = database.QueryReader("SELECT IP, UserGroup FROM Users"))
{
com.CommandText = "SELECT * FROM Users";
using (var reader = com.ExecuteReader())
{
while(reader.Read())
while (reader.Read())
{
if (Tools.GetIPv4Address(reader.Get<string>("IP")) == ip)
{
string group = reader.Get<string>("UserGroup");
return Tools.GetGroup(group);
}
return Tools.GetGroup(reader.Get<string>("UserGroup"));
}
}
}
}
catch (Exception ex)
{
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex.ToString());
Log.ConsoleError("GetGroupForIP SQL returned an error: " + ex);
}
return Tools.GetGroup("default");
}
@ -373,20 +298,17 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
QueryResult result;
if (string.IsNullOrEmpty(user.Address))
{
com.CommandText = "SELECT * FROM Users WHERE Username=@name";
com.AddParameter("@name", user.Name);
result = database.QueryReader("SELECT * FROM Users WHERE Username=@0", user.Name);
}
else
{
com.CommandText = "SELECT * FROM Users WHERE IP=@ip";
com.AddParameter("@ip", user.Address);
result = database.QueryReader("SELECT * FROM Users WHERE IP=@0", user.Address);
}
using (var reader = com.ExecuteReader())
using (var reader = result)
{
if (reader.Read())
{
@ -396,7 +318,6 @@ namespace TShockAPI.DB
}
}
}
}
catch (Exception ex)
{
throw new UserManagerException("GetUserID SQL returned an error", ex);

View file

@ -20,8 +20,9 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using Microsoft.Xna.Framework;
using System.Xml;
using Microsoft.Xna.Framework;
using MySql.Data.MySqlClient;
using Terraria;
namespace TShockAPI.DB
@ -34,16 +35,15 @@ namespace TShockAPI.DB
{
database = db;
using (var com = database.CreateCommand())
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText =
"CREATE TABLE IF NOT EXISTS 'Warps' ('X' NUMERIC, 'Y' NUMERIC, 'WarpName' TEXT PRIMARY KEY, 'WorldID' TEXT);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText =
"CREATE TABLE IF NOT EXISTS Warps (X INT(11), Y INT(11), WarpName VARCHAR(255) PRIMARY, WorldID VARCHAR(255));";
com.ExecuteNonQuery();
var table = new SqlTable("Warps",
new SqlColumn("WarpName", MySqlDbType.VarChar, 50) { Primary = true},
new SqlColumn("X", MySqlDbType.Int32),
new SqlColumn("Y", MySqlDbType.Int32),
new SqlColumn("WorldID", MySqlDbType.Text),
new SqlColumn("Private", MySqlDbType.Text)
);
var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite ? (IQueryBuilder)new SqliteQueryCreator() : new MysqlQueryCreator());
creator.EnsureExists(table);
String file = Path.Combine(TShock.SavePath, "warps.xml");
String name = "";
@ -102,16 +102,10 @@ namespace TShockAPI.DB
case XmlNodeType.EndElement:
if (reader.Name.Equals("Warp"))
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
com.CommandText = "INSERT OR IGNORE INTO Warps VALUES (@tx, @ty,@name, @worldid);";
else if (TShock.Config.StorageType.ToLower() == "mysql")
com.CommandText = "INSERT IGNORE INTO Warps SET X=@tx, Y=@ty, WarpName=@name, WorldID=@worldid;";
com.AddParameter("@tx", x1);
com.AddParameter("@ty", y1);
com.AddParameter("@name", name);
com.AddParameter("@worldid", world);
com.ExecuteNonQuery();
com.Parameters.Clear();
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO Warps VALUES (@0, @1,@2, @3);" :
"INSERT IGNORE INTO Warps SET X=@0, Y=@1, WarpName=@2, WorldID=@3;";
database.Query(query, x1, y1, name, world);
}
break;
}
@ -122,24 +116,19 @@ namespace TShockAPI.DB
String path = Path.Combine(TShock.SavePath, "old_configs");
String file2 = Path.Combine(path, "warps.xml");
if (!Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
Directory.CreateDirectory(path);
if (File.Exists(file2))
File.Delete(file2);
//File.Move(file, file2);
}
}
}
public void ConvertDB()
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "UPDATE Warps SET WorldID=@worldid";
com.AddParameter("@worldid", Main.worldID.ToString());
com.ExecuteNonQuery();
}
database.Query("UPDATE Warps SET WorldID=@0", Main.worldID.ToString());
}
catch (Exception ex)
{
@ -151,17 +140,9 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "INSERT INTO Warps (X, Y, WarpName, WorldID) VALUES (@x, @y, @name, @worldid);";
com.AddParameter("@x", x);
com.AddParameter("@y", y);
com.AddParameter("@name", name.ToLower());
com.AddParameter("@worldid", worldid);
com.ExecuteNonQuery();
database.Query("INSERT INTO Warps (X, Y, WarpName, WorldID) VALUES (@0, @1, @2, @3);", x, y, name, worldid);
return true;
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -173,15 +154,9 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "DELETE FROM Warps WHERE WarpName=@name AND WorldID=@worldid";
com.AddParameter("@name", name.ToLower());
com.AddParameter("@worldid", Main.worldID.ToString());
com.ExecuteNonQuery();
database.Query("DELETE FROM Warps WHERE WarpName=@0 AND WorldID=@1", name, Main.worldID.ToString());
return true;
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
@ -193,18 +168,18 @@ namespace TShockAPI.DB
{
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT * FROM Warps WHERE WarpName=@name AND WorldID=@worldid";
com.AddParameter("@name", name);
com.AddParameter("@worldid", Main.worldID.ToString());
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Warps WHERE WarpName=@0 AND WorldID=@1", name, Main.worldID.ToString()))
{
if (reader.Read())
{
return new Warp(new Vector2(reader.Get<int>("X"), reader.Get<int>("Y")), reader.Get<string>("WarpName"), reader.Get<string>("WorldID"));
try
{
return new Warp(new Vector2(reader.Get<int>("X"), reader.Get<int>("Y")), reader.Get<string>("WarpName"), reader.Get<string>("WorldID"), reader.Get<string>("Private"));
}
catch
{
return new Warp(new Vector2(reader.Get<int>("X"), reader.Get<int>("Y")), reader.Get<string>("WarpName"), reader.Get<string>("WorldID"), "0");
}
reader.Close();
}
}
}
@ -220,20 +195,25 @@ namespace TShockAPI.DB
/// </summary>
/// <param name="worldid">World name to get warps from</param>
/// <returns>List of warps with only their names</returns>
public List<Warp> ListAllWarps(string worldid)
public List<Warp> ListAllPublicWarps(string worldid)
{
var warps = new List<Warp>();
try
{
using (var com = database.CreateCommand())
{
com.CommandText = "SELECT WarpName FROM Warps WHERE WorldID=@worldid";
com.AddParameter("@worldid", worldid);
using (var reader = com.ExecuteReader())
using (var reader = database.QueryReader("SELECT * FROM Warps WHERE WorldID=@0", worldid))
{
while (reader.Read())
{
try
{
if (reader.Get<String>("Private") == "0" || reader.Get<String>("Private") == null)
warps.Add(new Warp { WarpName = reader.Get<string>("WarpName") });
}
catch
{
warps.Add(new Warp { WarpName = reader.Get<string>("WarpName") });
}
}
}
}
catch (Exception ex)
@ -242,6 +222,28 @@ namespace TShockAPI.DB
}
return warps;
}
/// <summary>
/// Gets all the warps names from world
/// </summary>
/// <param name="worldid">World name to get warps from</param>
/// <returns>List of warps with only their names</returns>
public bool HideWarp(string warp, bool state)
{
try
{
string query = "UPDATE Warps SET Private=@0 WHERE WarpName=@1 AND WorldID=@2";
database.Query(query, state ? "1" : "0", warp, Main.worldID.ToString());
return true;
}
catch (Exception ex)
{
Log.Error(ex.ToString());
return false;
}
}
}
public class Warp
@ -249,12 +251,14 @@ namespace TShockAPI.DB
public Vector2 WarpPos { get; set; }
public string WarpName { get; set; }
public string WorldWarpID { get; set; }
public string Private { get; set; }
public Warp(Vector2 warppos, string name, string worldname)
public Warp(Vector2 warppos, string name, string worldid, string hidden)
{
WarpPos = warppos;
WarpName = name;
WorldWarpID = worldname;
WorldWarpID = worldid;
Private = hidden;
}
public Warp()
@ -262,6 +266,7 @@ namespace TShockAPI.DB
WarpPos = Vector2.Zero;
WarpName = null;
WorldWarpID = string.Empty;
Private = "0";
}
}
}

317
TShockAPI/DBTools.cs Normal file
View file

@ -0,0 +1,317 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using TShockAPI.DB;
namespace TShockAPI
{
public class DBTools
{
internal static IDbConnection database;
/// <summary>
/// Creates a Table, within the current open DB
/// </summary>
/// <param name="name">Name of the Table</param>
/// <param name="columns">The list of columns that the Table will have</param>
/// <param name="IfNotExists">Only try create Table if it does not exist</param>
public static void CreateTable(string name, List<Column> columns, bool IfNotExists =true)
{
//Build up Creation string :)
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE ");
if (IfNotExists)
sb.Append("IF NOT EXISTS ");
if (TShock.Config.StorageType.ToLower() == "sqlite")
sb.Append("'" + name + "' (");
else if (TShock.Config.StorageType.ToLower() == "mysql")
sb.Append(name + " (");
int count = 0;
foreach (Column column in columns)
{
count++;
if (column.Type.ToLower() == "int")
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
sb.Append(column.Name + " NUMERIC ");
else if (TShock.Config.StorageType.ToLower() == "mysql")
sb.Append(column.Name + " INT(255) ");
}
else if (column.Type.ToLower() == "string")
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
sb.Append(column.Name + " TEXT ");
else if (TShock.Config.StorageType.ToLower() == "mysql")
sb.Append(column.Name + " VARCHAR(255) ");
}
if (column.Unique)
sb.Append("UNIQUE");
if (columns.Count == count)
sb.Append(")");
else
sb.Append(", ");
}
database.Query(sb.ToString());
}
/// <summary>
/// Inserts a list of values into a Table, if conditions are met
/// </summary>
/// <param name="tablename">Name of the Table</param>
/// <param name="Ignore">Ignore insert if feild is unique and there is already a exact entry</param>
/// <param name="Values">The list of values to enter into the table</param>
/// <param name="WhereStatements">The list of where statements that must be met, can be an empty list</param>
public static int InsertTable(string tablename, bool Ignore, List<ColumnData> Values, List<ColumnData> WhereStatements)
{
StringBuilder sb = new StringBuilder();
sb.Append("INSERT ");
if (Ignore)
{
if (TShock.Config.StorageType.ToLower() == "sqlite")
sb.Append("OR IGNORE ");
else if (TShock.Config.StorageType.ToLower() == "mysql")
sb.Append("IGNORE ");
}
if (TShock.Config.StorageType.ToLower() == "sqlite")
sb.Append("INTO '" + tablename + "' (");
else if (TShock.Config.StorageType.ToLower() == "mysql")
sb.Append("INTO " + tablename + " ");
using (var com = database.CreateCommand())
{
//Values
if (TShock.Config.StorageType.ToLower() == "sqlite")
{
int count = 0;
foreach (ColumnData columnname in Values)
{
count++;
if (Values.Count != count)
sb.Append(columnname.Name + ", ");
else
sb.Append(columnname.Name + ") ");
}
sb.Append("VALUES (");
count = 0;
foreach (ColumnData columnname in Values)
{
count++;
if (Values.Count != count)
{
sb.Append("@" + columnname.Name.ToLower() + ", ");
com.AddParameter("@" + columnname.Name.ToLower(), columnname.Value);
}
else
{
sb.Append("@" + columnname.Name.ToLower() + ") ");
com.AddParameter("@" + columnname.Name.ToLower(), columnname.Value);
}
}
}
else if (TShock.Config.StorageType.ToLower() == "mysql")
{
sb.Append("SET ");
int count = 0;
foreach (ColumnData columnname in Values)
{
count++;
if (Values.Count != count)
{
sb.Append("@" + columnname.Name.ToLower() + "=" + columnname.Value + ", ");
com.AddParameter("@" + columnname.Name.ToLower(), columnname.Value);
}
else
{
sb.Append("@" + columnname.Name.ToLower() + "=" + columnname.Value + ") ");
com.AddParameter("@" + columnname.Name.ToLower(), columnname.Value);
}
}
}
//Where Statement (if any)
if (WhereStatements.Count > 0)
{
sb.Append("WHERE ");
int count = 0;
foreach (ColumnData columnname in WhereStatements)
{
count++;
if (Values.Count != count)
{
sb.Append("@" + columnname.Name.ToLower() + "-where" + "=" + columnname.Value + " AND ");
com.AddParameter("@" + columnname.Name.ToLower() + "-where", columnname.Value);
}
else
{
sb.Append("@" + columnname.Name.ToLower() + "-where" + "=" + columnname.Value + ";");
com.AddParameter("@" + columnname.Name.ToLower() + "-where", columnname.Value);
}
}
}
com.CommandText = sb.ToString();
using (var reader = com.ExecuteReader())
return reader.RecordsAffected;
}
}
/// <summary>
/// Returns a list of values from a given Table, where conditions are met
/// </summary>
/// <param name="tablename">Name of the Table</param>
/// <param name="getcolumn">The name of the column you are getting the values from</param>
/// <param name="WhereStatements">The list of where statements that must be met, can be an empty list</param>
public static List<object> ReadTable(string tablename, string getcolumn, List<ColumnData> WhereStatements)
{
StringBuilder sb = new StringBuilder();
List<object> ReturnedValues = new List<object>();
sb.Append("SELECT * FROM " + tablename + " ");
using (var com = database.CreateCommand())
{
//Where Statement (if any)
if (WhereStatements.Count > 0)
{
sb.Append("WHERE ");
int count = 0;
foreach (ColumnData columnname in WhereStatements)
{
count++;
if (WhereStatements.Count != count)
{
sb.Append(columnname.Name + " =" + columnname.Value + " AND ");
}
else
{
sb.Append(columnname.Name + " =" + columnname.Value);
}
}
}
com.CommandText = sb.ToString();
using (var reader = com.ExecuteReader())
{
while (reader.Read())
ReturnedValues.Add(reader.Get<object>(getcolumn));
}
}
return ReturnedValues;
}
/// <summary>
/// Sets values in a Table, where statements are met
/// </summary>
/// <param name="tablename">Name of the Table</param>
/// <param name="setcolumn">The column data you are setting</param>
/// <param name="WhereStatements">The list of where statements that must be met, can be an empty list</param>
public static int SetTable(string tablename, ColumnData setcolumn, List<ColumnData> WhereStatements)
{
StringBuilder sb = new StringBuilder();
sb.Append("UPDATE " + tablename + " SET " + setcolumn.Name + "=@setcolumn ");
using (var com = database.CreateCommand())
{
//Where Statement (if any)
if (WhereStatements.Count > 0)
{
sb.Append("WHERE ");
int count = 0;
foreach (ColumnData columnname in WhereStatements)
{
count++;
if (WhereStatements.Count != count)
{
sb.Append(columnname.Name + " =" + columnname.Value + " AND ");
}
else
{
sb.Append(columnname.Name + " =" + columnname.Value);
}
}
}
com.CommandText = sb.ToString();
com.AddParameter("@setcolumn", setcolumn.Value);
using (var reader = com.ExecuteReader())
return reader.RecordsAffected;
}
}
}
public class Column
{
public string Name { get; set; }
public string Type { get; set; }
public bool Unique { get; set; }
public string Parameters { get; set; }
/// <summary>
/// The class for creating a new column type
/// </summary>
/// <param name="name">Name of the column</param>
/// <param name="unique">Whether there can be more than one exact value in the column</param>
/// <param name="type">The type of column, currently the api only supports "string" or "int"</param>
/// <param name="parameters">Extra SQL parameters given, can cause errors cross different SQL (SQLite and MySql)</param>
public Column(string name, bool unique, string type, string parameters = "")
{
Name = name;
Type = type;
Unique = unique;
Parameters = parameters;
}
public Column()
{
Name = string.Empty;
Type = string.Empty;
Unique = false;
Parameters = string.Empty;
}
}
public class ColumnData
{
public string Name { get; set; }
public object Value { get; set; }
/// <summary>
/// The class for testing, inserting or setting column data
/// </summary>
/// <param name="name">Column Name</param>
/// <param name="value">Column Value</param>
public ColumnData(string name, object value)
{
Name = name;
Value = value;
}
public ColumnData()
{
Name = string.Empty;
Value = string.Empty;
}
}
}

View file

@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Data;
namespace TShockAPI.DB
{
public static class DbExt
{
/// <summary>
/// Executes a query on a database.
/// </summary>
/// <param name="olddb">Database to query</param>
/// <param name="query">Query string with parameters as @0, @1, etc.</param>
/// <param name="args">Parameters to be put in the query</param>
/// <returns>Rows affected by query</returns>
public static int Query(this IDbConnection olddb, string query, params object[] args)
{
using (var db = olddb.CloneEx())
{
db.Open();
using (var com = db.CreateCommand())
{
com.CommandText = query;
for (int i = 0; i < args.Length; i++)
com.AddParameter("@" + i, args[i]);
return com.ExecuteNonQuery();
}
}
}
/// <summary>
/// Executes a query on a database.
/// </summary>
/// <param name="olddb">Database to query</param>
/// <param name="query">Query string with parameters as @0, @1, etc.</param>
/// <param name="args">Parameters to be put in the query</param>
/// <returns>Query result as IDataReader</returns>
public static QueryResult QueryReader(this IDbConnection olddb, string query, params object[] args)
{
var db = olddb.CloneEx();
db.Open();
using (var com = db.CreateCommand())
{
com.CommandText = query;
for (int i = 0; i < args.Length; i++)
com.AddParameter("@" + i, args[i]);
return new QueryResult(db, com.ExecuteReader());
}
}
public static IDbDataParameter AddParameter(this IDbCommand command, string name, object data)
{
var parm = command.CreateParameter();
parm.ParameterName = name;
parm.Value = data;
command.Parameters.Add(parm);
return parm;
}
public static IDbConnection CloneEx(this IDbConnection conn)
{
var clone = (IDbConnection)Activator.CreateInstance(conn.GetType());
clone.ConnectionString = conn.ConnectionString;
return clone;
}
public static SqlType GetSqlType(this IDbConnection conn)
{
var name = conn.GetType().Name;
if (name == "SqliteConnection")
return SqlType.Sqlite;
if (name == "MySqlConnection")
return SqlType.Mysql;
return SqlType.Unknown;
}
static readonly Dictionary<Type, Func<IDataReader, int, object>> ReadFuncs = new Dictionary<Type, Func<IDataReader, int, object>>()
{
{typeof(bool), (s, i) => s.GetBoolean(i)},
{typeof(byte), (s, i) => s.GetByte(i)},
{typeof(Int16), (s, i) => s.GetInt16(i)},
{typeof(Int32), (s, i) => s.GetInt32(i)},
{typeof(Int64), (s, i) => s.GetInt64(i)},
{typeof(string), (s, i) => s.GetString(i)},
{typeof(decimal), (s, i) => s.GetDecimal(i)},
{typeof(float), (s, i) => s.GetFloat(i)},
{typeof(double), (s, i) => s.GetDouble(i)},
{typeof(object), (s, i) => s.GetValue(i)},
};
public static T Get<T>(this IDataReader reader, string column)
{
return reader.Get<T>(reader.GetOrdinal(column));
}
public static T Get<T>(this IDataReader reader, int column)
{
if (ReadFuncs.ContainsKey(typeof(T)))
return (T)ReadFuncs[typeof(T)](reader, column);
throw new NotImplementedException();
}
}
public enum SqlType
{
Unknown,
Sqlite,
Mysql
}
public class QueryResult : IDisposable
{
public IDbConnection Connection { get; protected set; }
public IDataReader Reader { get; protected set; }
public QueryResult(IDbConnection conn, IDataReader reader)
{
Connection = conn;
Reader = reader;
}
public void Dispose()
{
Reader.Dispose();
Connection.Dispose();
}
public bool Read()
{
return Reader.Read();
}
public T Get<T>(string column)
{
return Reader.Get<T>(Reader.GetOrdinal(column));
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TShockAPI
{
public static class LinqExt
{
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null) throw new ArgumentNullException("source");
if (action == null) throw new ArgumentNullException("action");
foreach (T item in source)
action(item);
}
}
}

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TShockAPI.Extensions
{
public static class RandomExt
{
public static string NextString(this Random rand, int length)
{
var sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
switch (rand.Next(0, 3))
{
case 0:
sb.Append((char)rand.Next('a', 'z' + 1));
break;
case 1:
sb.Append((char)rand.Next('A', 'Z' + 1));
break;
case 2:
sb.Append((char)rand.Next('0', '9' + 1));
break;
}
}
return sb.ToString();
}
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TShockAPI
{
public static class StringExt
{
//Can't name it Format :(
public static String SFormat(this String str, params object[] args)
{
return String.Format(str, args);
}
}
}

View file

@ -17,17 +17,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.IO;
using Terraria;
namespace TShockAPI
{
internal class FileTools
public class FileTools
{
public static string RulesPath { get { return Path.Combine(TShock.SavePath, "rules.txt"); } }
public static string MotdPath { get { return Path.Combine(TShock.SavePath, "motd.txt"); } }
public static string WhitelistPath { get { return Path.Combine(TShock.SavePath, "whitelist.txt"); } }
public static string RememberedPosPath { get { return Path.Combine(TShock.SavePath, "oldpos.xml"); } }
public static string ConfigPath { get { return Path.Combine(TShock.SavePath, "config.json"); } }
internal static string RulesPath { get { return Path.Combine(TShock.SavePath, "rules.txt"); } }
internal static string MotdPath { get { return Path.Combine(TShock.SavePath, "motd.txt"); } }
internal static string WhitelistPath { get { return Path.Combine(TShock.SavePath, "whitelist.txt"); } }
internal static string RememberedPosPath { get { return Path.Combine(TShock.SavePath, "oldpos.xml"); } }
internal static string ConfigPath { get { return Path.Combine(TShock.SavePath, "config.json"); } }
public static void CreateFile(string file)
{

View file

@ -340,7 +340,7 @@ namespace TShockAPI
if ((DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds < 1000)
{
args.Player.SendMessage("Please wait another " + (1000 - (DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds).ToString() + " milliseconds before placing/destroying tiles", Color.Red);
args.Player.SendMessage("Please wait another " + (1000 - (DateTime.UtcNow - args.Player.LastExplosive).TotalMilliseconds) + " milliseconds before placing/destroying tiles", Color.Red);
args.Player.SendTileSquare(x, y);
return true;
}
@ -414,6 +414,18 @@ namespace TShockAPI
byte owner = args.Data.ReadInt8();
byte type = args.Data.ReadInt8();
if (ident > Main.maxProjectiles || ident < 0)
{
Tools.HandleGriefer(args.Player, TShock.Config.ExplosiveAbuseReason);
return true;
}
if ((vely == 0f || velx == 0f) && type == 23)
{
Tools.HandleGriefer(args.Player, TShock.Config.ProjectileAbuseReason);
return true;
}
if (type == 29 || type == 28 || type == 37)
{
Log.Debug(string.Format("Explosive(PlyXY:{0}_{1}, Type:{2})", args.Player.TileX, args.Player.TileY, type));

View file

@ -29,10 +29,17 @@ namespace TShockAPI
public Group Parent { get; protected set; }
public int Order { get; set; }
public Group(string groupname, Group parentgroup = null)
public byte R = 255;
public byte G = 255;
public byte B = 255;
public Group(string groupname, Group parentgroup = null, string ChatColor = "255,255,255")
{
Name = groupname;
Parent = parentgroup;
byte.TryParse(ChatColor.Split(',')[0], out R);
byte.TryParse(ChatColor.Split(',')[1], out G);
byte.TryParse(ChatColor.Split(',')[2], out B);
}
public virtual bool HasPermission(string permission)
@ -100,6 +107,9 @@ namespace TShockAPI
public SuperAdminGroup()
: base("superadmin")
{
R = (byte)TShock.Config.SuperAdminChatRGB[0];
G = (byte)TShock.Config.SuperAdminChatRGB[1];
B = (byte)TShock.Config.SuperAdminChatRGB[2];
}
public override bool HasPermission(string permission)

View file

@ -16,11 +16,7 @@ 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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace TShockAPI
{

View file

@ -17,10 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Terraria;
using XNAHelpers;

View file

@ -17,11 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Terraria;
using TerrariaAPI;
using XNAHelpers;

157
TShockAPI/PacketBufferer.cs Normal file
View file

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net.Sockets;
using System.Text;
using Microsoft.Xna.Framework;
using Terraria;
using TerrariaAPI;
using TerrariaAPI.Hooks;
namespace TShockAPI
{
public class PacketBufferer : IDisposable
{
/// <summary>
/// Maximum number of bytes to send per update per socket
/// </summary>
public int BytesPerUpdate { get; set; }
PacketBuffer[] buffers = new PacketBuffer[Netplay.serverSock.Length];
int[] Bytes = new int[52];
int[] Packets = new int[52];
int[] Compressed = new int[52];
Command dump;
Command flush;
public PacketBufferer()
{
BytesPerUpdate = 0xFFFF;
for (int i = 0; i < buffers.Length; i++)
buffers[i] = new PacketBuffer();
#if DEBUG_NET
dump = new Command("superadmin", Dump, "netdump");
flush = new Command("superadmin", Flush, "netflush");
Commands.ChatCommands.Add(dump);
Commands.ChatCommands.Add(flush);
#endif
ServerHooks.SendBytes += ServerHooks_SendBytes;
ServerHooks.SocketReset += ServerHooks_SocketReset;
GameHooks.PostUpdate += GameHooks_Update;
}
public void Dispose()
{
#if DEBUG_NET
Commands.ChatCommands.Remove(dump);
Commands.ChatCommands.Remove(flush);
#endif
ServerHooks.SendBytes -= ServerHooks_SendBytes;
ServerHooks.SocketReset -= ServerHooks_SocketReset;
GameHooks.PostUpdate -= GameHooks_Update;
}
void Dump(CommandArgs args)
{
var sb = new StringBuilder();
sb.AppendLine("{0,-25}{1,-25}{2,-25}{3}".SFormat("Name:", "Packets", "Bytes", "Compression"));
for (int i = 1; i < Bytes.Length; i++)
{
sb.AppendLine("{0,-25}{1,-25}{2,-25}{3}".SFormat(Enum.GetName(typeof(PacketTypes), i) + ":", Packets[i], Bytes[i], Compressed[i]));
}
File.WriteAllText(Path.Combine(TShock.SavePath, "dmp.txt"), sb.ToString());
}
void Flush(CommandArgs args)
{
Bytes = new int[52];
Packets = new int[52];
Compressed = new int[52];
}
void GameHooks_Update(GameTime obj)
{
for (int i = 0; i < Netplay.serverSock.Length; i++)
{
if (Netplay.serverSock[i] == null || !Netplay.serverSock[i].active)
continue;
if (!Netplay.serverSock[i].tcpClient.Client.Poll(0, SelectMode.SelectWrite))
continue;
byte[] buff = buffers[i].GetBytes(BytesPerUpdate);
if (buff == null)
continue;
try
{
Netplay.serverSock[i].tcpClient.Client.Send(buff);
}
catch (ObjectDisposedException)
{
}
catch (SocketException)
{
}
}
}
void ServerHooks_SocketReset(ServerSock socket)
{
buffers[socket.whoAmI] = new PacketBuffer();
}
void ServerHooks_SendBytes(ServerSock socket, byte[] buffer, int offset, int count, HandledEventArgs e)
{
e.Handled = true;
lock (buffers[socket.whoAmI])
{
#if DEBUG_NET
int size = (count - offset);
var pt = buffer[offset + 4];
Packets[pt]++;
Bytes[pt] += size;
Compressed[pt] += Compress(buffer, offset, count);
#endif
buffers[socket.whoAmI].AddRange(new MemoryStream(buffer, offset, count).ToArray());
}
}
#if DEBUG_NET
static int Compress(byte[] buffer, int offset, int count)
{
using (var ms = new MemoryStream())
{
using (var gzip = new GZipStream(ms, CompressionMode.Compress, true))
{
gzip.Write(buffer, offset, count);
}
return (int)ms.Length;
}
}
#endif
}
public class PacketBuffer : List<byte>
{
public byte[] GetBytes(int max)
{
lock (this)
{
if (this.Count < 1)
return null;
var ret = new byte[Math.Min(max, this.Count)];
this.CopyTo(0, ret, 0, ret.Length);
this.RemoveRange(0, ret.Length);
return ret;
}
}
}
}

View file

@ -36,5 +36,5 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.1.3.0723")]
[assembly: AssemblyFileVersion("3.1.3.0723")]
[assembly: AssemblyVersion("3.2.0.0805")]
[assembly: AssemblyFileVersion("3.2.0.0805")]

View file

@ -18,12 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Terraria;
namespace TShockAPI
@ -36,7 +35,7 @@ namespace TShockAPI
public static int ListenPort;
public static bool ContinueServer = true;
public static string Response = "";
private static bool Started = false;
private static bool Started;
private static UdpClient listener;
public static void StartThread()
@ -55,9 +54,9 @@ namespace TShockAPI
try
{
Console.WriteLine(string.Format("RconHandler is running at UDP port {0} and password is {1}",
ListenPort.ToString(),
ListenPort,
Password));
Thread listen = new Thread(new ThreadStart(Listener));
Thread listen = new Thread(Listener);
listen.Start();
while (true)
{
@ -87,7 +86,7 @@ namespace TShockAPI
catch (SocketException e)
{
if (e.SocketErrorCode == SocketError.AddressAlreadyInUse)
Log.ConsoleError("Could not bind to " + ListenPort.ToString() + ". Are you sure you don't have another instance running?");
Log.ConsoleError("Could not bind to " + ListenPort + ". Are you sure you don't have another instance running?");
}
catch (Exception e)
{
@ -150,7 +149,7 @@ namespace TShockAPI
args[1] = args[0] = "";
string command = string.Join(" ", args.ToArray());
command = command.TrimEnd(' ').TrimEnd('\0').TrimStart(' ');
Log.ConsoleInfo("Rcon from " + EP.ToString() + ":" + command);
Log.ConsoleInfo("Rcon from " + EP + ":" + command);
Response = "";
response = ExecuteCommand(command);
response += "\n" + Response;
@ -160,7 +159,7 @@ namespace TShockAPI
else
{
response = "Bad rconpassword.\n";
Log.ConsoleInfo("Bad rconpassword from " + EP.ToString());
Log.ConsoleInfo("Bad rconpassword from " + EP);
}
}
else
@ -186,7 +185,7 @@ namespace TShockAPI
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.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum.ToString(),
TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum,
Netplay.password != "" ? 1 : 0);
if (challenge != "")
infostring += @"\challenge\" + challenge;
@ -205,7 +204,7 @@ namespace TShockAPI
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.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum.ToString(),
TShock.Config.HardcoreOnly ? 1 : 0, TShock.VersionNum,
Netplay.password != "" ? 1 : 0) + "\n";
if (challenge != "")
statusstring += @"\challenge\" + challenge;
@ -260,7 +259,7 @@ namespace TShockAPI
if (player != null && player.Active)
{
count++;
Response += (string.Format("{0} 0 0 {1}({2}) {3} {4} 0 0", count, player.Name, player.Group.Name, Netplay.serverSock[player.Index].tcpClient.Client.RemoteEndPoint.ToString())) + "\n";
Response += (string.Format("{0} 0 0 {1}({2}) {3} {4} 0 0", count, player.Name, player.Group.Name, Netplay.serverSock[player.Index].tcpClient.Client.RemoteEndPoint)) + "\n";
}
}
}
@ -334,7 +333,7 @@ namespace TShockAPI
catch (SocketException e)
{
if (e.SocketErrorCode == SocketError.AddressAlreadyInUse)
Log.ConsoleError("Could not bind to " + ListenPort.ToString() + ". Are you sure you don't have another instance running?");
Log.ConsoleError("Could not bind to " + ListenPort + ". Are you sure you don't have another instance running?");
}
catch (Exception e)
{

View file

@ -1,154 +0,0 @@
/*
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.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Terraria;
using Microsoft.Xna.Framework;
using System.Xml;
namespace TShockAPI
{
class RemeberedPosManager
{
public static List<RemeberedPos> RemeberedPosistions = new List<RemeberedPos>();
public static void LoadPos()
{
try
{
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.IgnoreWhitespace = true;
using (XmlReader settingr = XmlReader.Create(FileTools.RememberedPosPath, xmlReaderSettings))
{
while (settingr.Read())
{
if (settingr.IsStartElement())
{
switch (settingr.Name)
{
case "Positions":
{
break;
}
case "Player":
{
if (settingr.Read())
{
string IP = null;
float X = 0;
float Y = 0;
settingr.Read();
if (settingr.Value != "" || settingr.Value != null)
IP = settingr.Value;
else
Log.Warn("IP is empty");
settingr.Read();
settingr.Read();
settingr.Read();
if (settingr.Value != "" || settingr.Value != null)
float.TryParse(settingr.Value, out X);
else
Log.Warn("X for IP " + IP + " is empty");
settingr.Read();
settingr.Read();
settingr.Read();
if (settingr.Value != "" || settingr.Value != null)
float.TryParse(settingr.Value, out Y);
else
Log.Warn("Y for IP " + IP + " is empty");
if (X != 0 && Y != 0)
RemeberedPosistions.Add(new RemeberedPos(IP, new Vector2(X, Y)));
}
break;
}
}
}
}
}
Log.Info("Read Remembered Positions");
}
catch
{
Log.Warn("Could not read Remembered Positions");
WriteSettings();
}
}
public static void WriteSettings()
{
try
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.NewLineChars = Environment.NewLine;
using (XmlWriter settingsw = XmlWriter.Create(FileTools.RememberedPosPath, xmlWriterSettings))
{
settingsw.WriteStartDocument();
settingsw.WriteStartElement("Positions");
foreach (RemeberedPos player in RemeberedPosistions)
{
settingsw.WriteStartElement("Player");
settingsw.WriteElementString("IP", player.IP);
settingsw.WriteElementString("X", player.Pos.X.ToString());
settingsw.WriteElementString("Y", player.Pos.Y.ToString());
settingsw.WriteEndElement();
}
settingsw.WriteEndElement();
settingsw.WriteEndDocument();
}
Log.Info("Wrote Remembered Positions");
}
catch
{
Log.Warn("Could not write Remembered Positions");
}
}
}
public class RemeberedPos
{
public string IP { get; set; }
public Vector2 Pos { get; set; }
public RemeberedPos(string ip, Vector2 pos)
{
IP = ip;
Pos = pos;
}
public RemeberedPos()
{
IP = string.Empty;
Pos = Vector2.Zero;
}
}
}

View file

@ -18,10 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Microsoft.Xna.Framework;
using Terraria;
using TerrariaAPI;
using TShockAPI.DB;
using TShockAPI.Net;
namespace TShockAPI
@ -38,21 +38,22 @@ namespace TShockAPI
public bool ReceivedInfo { get; set; }
public int Index { get; protected set; }
public DateTime LastPvpChange { get; protected set; }
public Rectangle TempArea = new Rectangle();
public Rectangle TempArea;
public DateTime LastExplosive { get; set; }
public DateTime LastTileChangeNotify { get; set; }
public bool InitSpawn = false;
public bool InitSpawn;
public bool DisplayLogs = true;
public Vector2 oldSpawn = Vector2.Zero;
public TSPlayer LastWhisper;
public int LoginAttempts { get; set; }
public Vector2 TeleportCoords = new Vector2(-1, -1);
public string UserAccountName { get; set; }
public bool HasBeenSpammedWithBuildMessage = false;
public bool IsLoggedIn = false;
public bool HasBeenSpammedWithBuildMessage;
public bool IsLoggedIn;
public int UserID = -1;
public bool HasBeenNaggedAboutLoggingIn = false;
Player FakePlayer = null;
public bool HasBeenNaggedAboutLoggingIn;
public bool TpLock = false;
Player FakePlayer;
public bool RealPlayer
{
@ -183,6 +184,8 @@ namespace TShockAPI
}
public bool Teleport(int tilex, int tiley)
{
if (!TpLock)
{
InitSpawn = false;
@ -191,46 +194,21 @@ 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)
if (!SendTileSquare(tilex, tiley, 150))
if (!SendTileSquare(tilex, tiley))
{
SendMessage("Warning, teleport failed due to being too close to the edge of the map.", Color.Red);
return false;
}
if (TPlayer.SpawnX > 0 && TPlayer.SpawnY > 0)
{
int spX = TPlayer.SpawnX;
int spY = TPlayer.SpawnY;
Main.tile[spX, spY].active = false;
SendTileSquare(spX, spY);
Spawn();
Main.tile[spX, spY].active = true;
SendTileSquare(spX, spY);
oldSpawn = new Vector2(spX, spY);
}
else
{
//Checks if Player has spawn point set (Server may think player does not have spawn)
if (oldSpawn != Vector2.Zero)
{
Main.tile[(int)oldSpawn.X, (int)oldSpawn.Y].active = false;
SendTileSquare((int)oldSpawn.X, (int)oldSpawn.Y);
Spawn();
Main.tile[(int)oldSpawn.X, (int)oldSpawn.Y].active = true;
SendTileSquare((int)oldSpawn.X, (int)oldSpawn.Y);
NetMessage.syncPlayers();
}
//Player has no spawn point set
else
{
Spawn();
}
}
SendTeleport(Main.spawnTileX, Main.spawnTileY);
return true;
}
SendMessage("Cannot teleport due to TP Lock", Color.Red);
return false;
}
public void Spawn()
{
@ -241,7 +219,7 @@ namespace TShockAPI
{
try
{
SendData(PacketTypes.TileSendSquare, "", size, (float)(x - (size / 2)), (float)(y - (size / 2)));
SendData(PacketTypes.TileSendSquare, "", size, (x - (size / 2)), (y - (size / 2)));
return true;
}
catch (Exception ex)
@ -253,7 +231,7 @@ namespace TShockAPI
public virtual void GiveItem(int type, string name, int width, int height, int stack)
{
int itemid = Terraria.Item.NewItem((int)X, (int)Y, width, height, type, stack, true);
int itemid = Item.NewItem((int)X, (int)Y, width, height, type, stack, true);
// This is for special pickaxe/hammers/swords etc
Main.item[itemid].SetDefaults(name);
// The set default overrides the wet and stack set by NewItem
@ -296,6 +274,12 @@ namespace TShockAPI
NetMessage.SendData((int)PacketTypes.TogglePVP, -1, -1, "", Index);
}
public virtual void SetTeam(int team)
{
Main.player[Index].team = team;
SendData(PacketTypes.PlayerTeam, "", Index);
}
public virtual void Whoopie(object time)
{
var time2 = (int)time;
@ -310,18 +294,18 @@ namespace TShockAPI
{
Main.player[0].inventory[player].SetDefaults("Whoopie Cushion");
Main.player[0].inventory[player].stack = 1;
SendData(TerrariaAPI.PacketTypes.PlayerSlot, "Whoopie Cushion", player, 0f);
SendData(PacketTypes.PlayerSlot, "Whoopie Cushion", player, 0f);
Main.player[player].position = TPlayer.position;
Main.player[player].selectedItem = 0;
Main.player[player].controlUseItem = true;
SendData(TerrariaAPI.PacketTypes.PlayerUpdate, number: player);
System.Threading.Thread.Sleep(500);
SendData(PacketTypes.PlayerUpdate, number: player);
Thread.Sleep(500);
Main.player[player].controlUseItem = false;
SendData(TerrariaAPI.PacketTypes.PlayerUpdate, number: player);
System.Threading.Thread.Sleep(50);
SendData(PacketTypes.PlayerUpdate, number: player);
Thread.Sleep(50);
}
Main.player[0].inventory[0] = oriinv;
SendData(TerrariaAPI.PacketTypes.PlayerSlot, oriinv.name, player, 0f);
SendData(PacketTypes.PlayerSlot, oriinv.name, player, 0f);
}
//Todo: Separate this into a few functions. SendTo, SendToAll, etc
@ -423,7 +407,7 @@ namespace TShockAPI
// Send all players updated tile sqaures
foreach (Vector2 coords in destroyedTiles.Keys)
{
TSPlayer.All.SendTileSquare((int)coords.X, (int)coords.Y, 3);
All.SendTileSquare((int)coords.X, (int)coords.Y, 3);
}
}
}

View file

@ -31,25 +31,24 @@ using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Linq;
using System.Threading;
using MySql.Data.MySqlClient;
using Community.CsharpSqlite.SQLiteClient;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using MySql.Data.MySqlClient;
using Terraria;
using TerrariaAPI;
using TerrariaAPI.Hooks;
using System.Text;
using TShockAPI.DB;
namespace TShockAPI
{
[APIVersion(1, 5)]
[APIVersion(1, 6)]
public class TShock : TerrariaPlugin
{
public static readonly Version VersionNum = Assembly.GetExecutingAssembly().GetName().Version;
public static readonly string VersionCodename = "Milestone 3";
public static readonly string VersionCodename = "Yes, we're adding Logblock style functionality soon, don't worry.";
public static string SavePath = "tshock";
@ -61,15 +60,12 @@ namespace TShockAPI
public static GroupManager Groups;
public static UserManager Users;
public static ItemManager Itembans;
public static RemeberedPosManager RememberedPos;
public static ConfigFile Config { get; set; }
public static IDbConnection DB;
public static bool OverridePort;
PacketBufferer bufferer;
public static Process TShockProcess;
public static bool OverridePort = false;
public static double ElapsedTime;
public override Version Version
{
@ -111,6 +107,9 @@ namespace TShockAPI
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...");
@ -127,7 +126,6 @@ namespace TShockAPI
{
string sql = Path.Combine(SavePath, "tshock.sqlite");
DB = new SqliteConnection(string.Format("uri=file://{0},Version=3", sql));
DB.Open();
}
else if (Config.StorageType.ToLower() == "mysql")
{
@ -135,14 +133,14 @@ namespace TShockAPI
{
var hostport = Config.MySqlHost.Split(':');
DB = new MySqlConnection();
DB.ConnectionString = String.Format("Server='{0}'; Port='{1}'; Database='{2}'; Uid='{3}'; Pwd='{4}';",
DB.ConnectionString =
String.Format("Server='{0}'; Port='{1}'; Database='{2}'; Uid='{3}'; Pwd='{4}';",
hostport[0],
hostport.Length > 1 ? hostport[1] : "3306",
Config.MySqlDbName,
Config.MySqlUsername,
Config.MySqlPassword
);
DB.Open();
}
catch (MySqlException ex)
{
@ -155,6 +153,8 @@ namespace TShockAPI
throw new Exception("Invalid storage type");
}
DBTools.database = DB;
Backups = new BackupManager(Path.Combine(SavePath, "backups"));
Backups.KeepFor = Config.BackupKeepFor;
Backups.Interval = Config.BackupInterval;
@ -165,6 +165,7 @@ namespace TShockAPI
Groups.LoadPermisions();
Regions = new RegionManager(DB);
Itembans = new ItemManager(DB);
RememberedPos = new RemeberedPosManager(DB);
Log.ConsoleInfo(string.Format("TShock Version {0} ({1}) now running.", Version, VersionCodename));
@ -177,27 +178,28 @@ namespace TShockAPI
NetHooks.GetData += GetData;
NetHooks.GreetPlayer += OnGreetPlayer;
NpcHooks.StrikeNpc += NpcHooks_OnStrikeNpc;
NetHooks.SendData += new NetHooks.SendDataD(NetHooks_SendData);
GetDataHandlers.InitGetDataHandler();
Commands.InitCommands();
//RconHandler.StartThread();
Log.ConsoleInfo("AutoSave " + (TShock.Config.AutoSave ? "Enabled" : "Disabled"));
Log.ConsoleInfo("Backups " + (Backups.Interval > 0 ? "Enabled" : "Disabled"));
}
if (Config.BufferPackets)
bufferer = new PacketBufferer();
void NetHooks_SendData(SendDataEventArgs e)
Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled"));
Log.ConsoleInfo("Backups " + (Backups.Interval > 0 ? "Enabled" : "Disabled"));
}
catch (Exception ex)
{
if (e.MsgID == PacketTypes.PlayerActive)
{
//Debug.WriteLine("Send: {0} ({1:X2})", (byte)e.MsgID, e.MsgID.ToString());
Log.Error("Fatal Startup Exception");
Log.Error(ex.ToString());
Environment.Exit(1);
}
}
public override void DeInitialize()
{
DB.Close();
GameHooks.PostInitialize -= OnPostInit;
GameHooks.Update -= OnUpdate;
ServerHooks.Join -= OnJoin;
@ -222,6 +224,25 @@ namespace TShockAPI
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Log.Error(e.ExceptionObject.ToString());
if (e.ExceptionObject.ToString().Contains("Terraria.Netplay.ListenForClients") ||
e.ExceptionObject.ToString().Contains("Terraria.Netplay.ServerLoop"))
{
var sb = new List<string>();
for (int i = 0; i < Netplay.serverSock.Length; i++)
{
if (Netplay.serverSock[i] == null)
{
sb.Add("Sock[" + i + "]");
}
else if (Netplay.serverSock[i].tcpClient == null)
{
sb.Add("Tcp[" + i + "]");
}
}
Log.Error(string.Join(", ", sb));
}
if (e.IsTerminating)
{
if (Main.worldPathName != null)
@ -229,7 +250,6 @@ namespace TShockAPI
Main.worldPathName += ".crash";
WorldGen.saveWorld();
}
DeInitialize();
}
}
@ -285,6 +305,7 @@ namespace TShockAPI
*/
public static int AuthToken = -1;
private void OnPostInit()
{
if (!File.Exists(Path.Combine(SavePath, "auth.lck")) && !File.Exists(Path.Combine(SavePath, "authcode.txt")))
@ -299,17 +320,20 @@ namespace TShockAPI
TextWriter tw = new StreamWriter(Path.Combine(SavePath, "authcode.txt"));
tw.WriteLine(AuthToken);
tw.Close();
} else if (File.Exists(Path.Combine(SavePath, "authcode.txt")))
}
else if (File.Exists(Path.Combine(SavePath, "authcode.txt")))
{
TextReader tr = new StreamReader(Path.Combine(SavePath, "authcode.txt"));
AuthToken = Convert.ToInt32(tr.ReadLine());
tr.Close();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("TShock Notice: authcode.txt is still present, and the AuthToken located in that file will be used.");
Console.WriteLine(
"TShock Notice: authcode.txt is still present, and the AuthToken located in that file will be used.");
Console.WriteLine("To become superadmin, join the game and type /auth " + AuthToken);
Console.WriteLine("This token will display until disabled by verification. (/auth-verify)");
Console.ForegroundColor = ConsoleColor.Gray;
} else
}
else
{
AuthToken = 0;
}
@ -318,6 +342,7 @@ namespace TShockAPI
private DateTime LastCheck = DateTime.UtcNow;
private void OnUpdate(GameTime time)
{
UpdateManager.UpdateProcedureCheck();
@ -329,13 +354,13 @@ namespace TShockAPI
if ((DateTime.UtcNow - LastCheck).TotalSeconds >= 1)
{
LastCheck = DateTime.UtcNow;
foreach (TSPlayer player in TShock.Players)
foreach (TSPlayer player in Players)
{
if (player != null && player.Active)
{
if (player.TilesDestroyed != null)
{
if (player.TileThreshold >= TShock.Config.TileThreshold)
if (player.TileThreshold >= Config.TileThreshold)
{
if (Tools.HandleTntUser(player, "Kill tile abuse detected."))
{
@ -355,7 +380,7 @@ namespace TShockAPI
for (int i = 0; i < inv.Length; i++)
{
if (inv[i] != null && TShock.Itembans.ItemIsBanned(inv[i].name))
if (inv[i] != null && Itembans.ItemIsBanned(inv[i].name))
{
player.Disconnect("Using banned item: " + inv[i].name + ", remove it and rejoin");
break;
@ -372,13 +397,14 @@ namespace TShockAPI
var player = new TSPlayer(ply);
if (Config.EnableDNSHostResolution)
{
player.Group = TShock.Users.GetGroupForIPExpensive(player.IP);
} else
player.Group = Users.GetGroupForIPExpensive(player.IP);
}
else
{
player.Group = TShock.Users.GetGroupForIP(player.IP);
player.Group = Users.GetGroupForIP(player.IP);
}
if (Tools.ActivePlayers() + 1 > TShock.Config.MaxSlots && !player.Group.HasPermission("reservedslot"))
if (Tools.ActivePlayers() + 1 > Config.MaxSlots && !player.Group.HasPermission("reservedslot"))
{
Tools.ForceKick(player, "Server is full");
handler.Handled = true;
@ -412,12 +438,9 @@ namespace TShockAPI
{
Log.Info(string.Format("{0} left.", tsplr.Name));
if (TShock.Config.RememberLeavePos)
if (Config.RememberLeavePos)
{
RemeberedPosManager.RemeberedPosistions.Add(new RemeberedPos(tsplr.IP,
new Vector2(tsplr.X / 16,
(tsplr.Y / 16) + 3)));
RemeberedPosManager.WriteSettings();
RememberedPos.InsertLeavePos(tsplr.Name, tsplr.IP, (int)(tsplr.X / 16), (int)(tsplr.Y / 16));
}
}
}
@ -439,15 +462,25 @@ namespace TShockAPI
}
if (msg.whoAmI != ply)
{
if (text.StartsWith("/playing"))
{
var names = Main.player.Where(p => p != null && p.active).Select(p => p.name).Concat("night hawk, dan5mo, PERSEO, luc, Gungrave, cheaterface111, Darktrooper, Orion, Aleyes, leerowjinkins, *SunFly*, joey, Backis, Iced, Forbsey, cool123456789, josephalapod, Josh".Split(new string[] { ", " }, StringSplitOptions.None));
tsplr.SendMessage(string.Format("Current players: {0}.", string.Join(", ", names)), 255, 240, 20);
e.Handled = true;
}
else
{
e.Handled = Tools.HandleGriefer(tsplr, "Faking Chat");
}
return;
}
if (tsplr.Group.HasPermission("adminchat") && !text.StartsWith("/") && Config.AdminChatEnabled)
{
Tools.Broadcast(TShock.Config.AdminChatPrefix + "<" + tsplr.Name + "> " + text,
(byte)TShock.Config.AdminChatRGB[0], (byte)TShock.Config.AdminChatRGB[1], (byte)TShock.Config.AdminChatRGB[2]);
Tools.Broadcast(Config.AdminChatPrefix + "<" + tsplr.Name + "> " + text,
tsplr.Group.R, tsplr.Group.G,
tsplr.Group.B);
e.Handled = true;
return;
}
@ -466,7 +499,11 @@ namespace TShockAPI
}
else
{
Log.Info(string.Format("{0} said: {1}", tsplr.Name, text));
Tools.Broadcast("<" + tsplr.Name + "> " + text,
tsplr.Group.R, tsplr.Group.G,
tsplr.Group.B);
//Log.Info(string.Format("{0} said: {1}", tsplr.Name, text));
e.Handled = true;
}
}
@ -493,15 +530,6 @@ namespace TShockAPI
if (text.StartsWith("exit"))
{
Tools.ForceKickAll("Server shutting down!");
var sb = new StringBuilder();
for (int i = 0; i < Main.maxItemTypes; i++)
{
string itemName = Main.itemName[i];
string itemID = (i).ToString();
sb.Append("ItemList.Add(\"" + itemName + "\");").AppendLine();
}
File.WriteAllText("item.txt", sb.ToString());
}
else if (text.StartsWith("playing") || text.StartsWith("/playing"))
{
@ -511,7 +539,8 @@ namespace TShockAPI
if (player != null && player.Active)
{
count++;
TSPlayer.Server.SendMessage(string.Format("{0} ({1}) [{2}]", player.Name, player.IP, player.Group.Name));
TSPlayer.Server.SendMessage(string.Format("{0} ({1}) [{2}]", player.Name, player.IP,
player.Group.Name));
}
}
TSPlayer.Server.SendMessage(string.Format("{0} players connected.", count));
@ -523,8 +552,8 @@ namespace TShockAPI
}
else if (text == "autosave")
{
Main.autoSave = TShock.Config.AutoSave = !TShock.Config.AutoSave;
Log.ConsoleInfo("AutoSave " + (TShock.Config.AutoSave ? "Enabled" : "Disabled"));
Main.autoSave = Config.AutoSave = !Config.AutoSave;
Log.ConsoleInfo("AutoSave " + (Config.AutoSave ? "Enabled" : "Disabled"));
e.Handled = true;
}
else if (text.StartsWith("/"))
@ -554,7 +583,8 @@ namespace TShockAPI
//Debug.WriteLine("Recv: {0:X} ({2}): {3} ({1:XX})", player.Index, (byte)type, player.TPlayer.dead ? "dead " : "alive", type.ToString());
// Stop accepting updates from player as this player is going to be kicked/banned during OnUpdate (different thread so can produce race conditions)
if ((TShock.Config.BanKillTileAbusers || TShock.Config.KickKillTileAbusers) && player.TileThreshold >= TShock.Config.TileThreshold && !player.Group.HasPermission("ignoregriefdetection"))
if ((Config.BanKillTileAbusers || Config.KickKillTileAbusers) &&
player.TileThreshold >= Config.TileThreshold && !player.Group.HasPermission("ignoregriefdetection"))
{
Log.Debug("Rejecting " + type + " from " + player.Name + " as this player is about to be kicked");
e.Handled = true;
@ -585,6 +615,9 @@ namespace TShockAPI
return;
}
NetMessage.SendData((int)PacketTypes.TimeSet, -1, -1, "", 0, 0, Main.sunModY, Main.moonModY);
NetMessage.syncPlayers();
Log.Info(string.Format("{0} ({1}) from '{2}' group joined.", player.Name, player.IP, player.Group.Name));
Tools.ShowFileToUser(player, "motd.txt");
@ -595,7 +628,9 @@ namespace TShockAPI
if (Config.AlwaysPvP)
{
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.SendMessage(
"PvP is forced! Enable PvP else you can't deal damage to other people. (People can kill you)",
Color.Red);
}
if (player.Group.HasPermission("causeevents") && Config.InfiniteInvasion)
{
@ -603,16 +638,9 @@ namespace TShockAPI
}
if (Config.RememberLeavePos)
{
foreach (RemeberedPos playerIP in RemeberedPosManager.RemeberedPosistions)
{
if (playerIP.IP == player.IP)
{
player.Teleport((int)playerIP.Pos.X, (int)playerIP.Pos.Y);
RemeberedPosManager.RemeberedPosistions.Remove(playerIP);
RemeberedPosManager.WriteSettings();
break;
}
}
var pos = RememberedPos.GetLeavePos(player.Name, player.IP);
player.Teleport((int)pos.X, (int)pos.Y);
player.SendTileSquare((int)pos.X, (int)pos.Y);
}
e.Handled = true;
}
@ -644,13 +672,13 @@ namespace TShockAPI
public static void StartInvasion()
{
Main.invasionType = 1;
if (TShock.Config.InfiniteInvasion)
if (Config.InfiniteInvasion)
{
Main.invasionSize = 20000000;
}
else
{
Main.invasionSize = 100 + (TShock.Config.InvasionMultiplier * Tools.ActivePlayers());
Main.invasionSize = 100 + (Config.InvasionMultiplier * Tools.ActivePlayers());
}
Main.invasionWarn = 0;
@ -664,7 +692,8 @@ namespace TShockAPI
}
}
static int KillCount = 0;
private static int KillCount;
public static void IncrementKills()
{
KillCount++;
@ -700,7 +729,7 @@ namespace TShockAPI
{
Vector2 tile = new Vector2(x, y);
Vector2 spawn = new Vector2(Main.spawnTileX, Main.spawnTileY);
return Vector2.Distance(spawn, tile) <= TShock.Config.SpawnProtectionRadius;
return Vector2.Distance(spawn, tile) <= Config.SpawnProtectionRadius;
}
public static bool HackedHealth(TSPlayer player)
@ -731,8 +760,23 @@ namespace TShockAPI
RconHandler.Password = file.RconPassword;
RconHandler.ListenPort = file.RconPort;
Type hash;
if (Tools.HashTypes.TryGetValue(file.HashAlgorithm, out hash))
{
lock (Tools.HashAlgo)
{
if (!Tools.HashAlgo.GetType().Equals(hash))
{
Tools.HashAlgo.Dispose();
Tools.HashAlgo = (HashAlgorithm)Activator.CreateInstance(Tools.HashTypes[file.HashAlgorithm]);
}
}
}
else
{
Log.ConsoleError("Invalid or not supported hashing algorithm: " + file.HashAlgorithm);
}
}
}
}

View file

@ -32,7 +32,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<OutputPath>..\..\serverplugins\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -93,22 +93,31 @@
<ItemGroup>
<Compile Include="BackupManager.cs" />
<Compile Include="DB\BanManager.cs" />
<Compile Include="DBTools.cs" />
<Compile Include="DB\IQueryBuilder.cs" />
<Compile Include="DB\ItemManager.cs" />
<Compile Include="DB\DbExt.cs" />
<Compile Include="DB\SqlColumn.cs" />
<Compile Include="DB\SqlTable.cs" />
<Compile Include="DB\SqlValue.cs" />
<Compile Include="Extensions\DbExt.cs" />
<Compile Include="DB\GroupManager.cs" />
<Compile Include="DB\UserManager.cs" />
<Compile Include="Extensions\RandomExt.cs" />
<Compile Include="Extensions\StringExt.cs" />
<Compile Include="IPackable.cs" />
<Compile Include="Commands.cs" />
<Compile Include="ConfigFile.cs" />
<Compile Include="FileTools.cs" />
<Compile Include="GetDataHandlers.cs" />
<Compile Include="Group.cs" />
<Compile Include="Extensions\LinqExt.cs" />
<Compile Include="Log.cs" />
<Compile Include="Net\NetTile.cs" />
<Compile Include="Net\WorldInfoMsg.cs" />
<Compile Include="DB\RegionManager.cs" />
<Compile Include="PacketBufferer.cs" />
<Compile Include="RconHandler.cs" />
<Compile Include="RememberPosManager.cs" />
<Compile Include="DB\RememberPosManager.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

View file

@ -18,17 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Net;
using Microsoft.Xna.Framework;
using Terraria;
using System.Linq;
using TerrariaAPI;
namespace TShockAPI
{
internal class Tools
public class Tools
{
public static Random Random = new Random();
//private static List<Group> groups = new List<Group>();
@ -145,7 +146,7 @@ namespace TShockAPI
TSPlayer.Server.SendMessage(log, color);
foreach (TSPlayer player in TShock.Players)
{
if (player != null && player.Active && player.Group.HasPermission("logs") && player.DisplayLogs)
if (player != null && player.Active && player.Group.HasPermission("logs") && player.DisplayLogs && TShock.Config.DisableSpewLogs == false)
player.SendMessage(log, color);
}
}
@ -312,7 +313,7 @@ namespace TShockAPI
/// <param name="reason">string reason</param>
public static void ForceKickAll(string reason)
{
foreach(TSPlayer player in TShock.Players)
foreach (TSPlayer player in TShock.Players)
{
if (player != null && player.Active)
{
@ -486,6 +487,15 @@ namespace TShockAPI
return ip != null ? ip.ToString() : "";
}
public static HashAlgorithm HashAlgo = new MD5Cng();
public static readonly Dictionary<string, Type> HashTypes = new Dictionary<string, Type>
{
{"sha512", typeof(SHA512Managed)},
{"sha256", typeof(SHA256Managed)},
{"md5", typeof(MD5Cng)},
};
/// <summary>
/// Returns a Sha256 string for a given string
/// </summary>
@ -493,16 +503,11 @@ namespace TShockAPI
/// <returns>string sha256</returns>
public static string HashPassword(string password)
{
using (var sha = new SHA512CryptoServiceProvider())
{
if (password == "")
{
return "nonexistent-password";
}
var bytes = sha.ComputeHash(Encoding.ASCII.GetBytes(password));
if (string.IsNullOrEmpty(password) || password == "non-existant password")
return "non-existant password";
var bytes = HashAlgo.ComputeHash(Encoding.ASCII.GetBytes(password));
return bytes.Aggregate("", (s, b) => s + b.ToString("X2"));
}
}
/// <summary>
/// Checks if the string contains any unprintable characters

View file

@ -16,14 +16,9 @@ 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.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Terraria;
namespace TShockAPI
{

View file

@ -25,6 +25,7 @@
#tphere - allow a player to teleport players to their position
#managewarp - allow player to add/delete warp locations
#managegroup - allow player to add/delete/modify groups
#manageitem - allow a player to add/delete item bans
#editspawn - allow player to enable/disable build protection
#cfg - allow player to view/change tshock configuration
#time - allow player to change time

View file

@ -1,5 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestList name="Bamboo" id="63a4ff11-fe54-4b77-97f5-2e5034a7c905" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<TestLinks>
<TestLink id="7601a790-d2fb-45d2-a612-1ae4de84eb61" name="regionmanagertest" storage="unittests\regionmanagertest.orderedtest" type="Microsoft.VisualStudio.TestTools.TestTypes.Ordered.AutoSuite, Microsoft.VisualStudio.QualityTools.Tips.OrderedTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="f28695ef-8181-4996-8783-b5059ce904b1" name="banmanagertest" storage="unittests\banmanagertest.orderedtest" type="Microsoft.VisualStudio.TestTools.TestTypes.Ordered.AutoSuite, Microsoft.VisualStudio.QualityTools.Tips.OrderedTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="b9c6b3d7-52d8-4b49-bfbf-933efa073ca8" name="itemmanagertest" storage="unittests\itemmanagertest.orderedtest" type="Microsoft.VisualStudio.TestTools.TestTypes.Ordered.AutoSuite, Microsoft.VisualStudio.QualityTools.Tips.OrderedTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
</TestLinks>
</TestList>
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<RunConfiguration id="943ada2e-478e-45be-b4b8-6f7d6d949602" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</TestList>

Binary file not shown.

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Trace and Test Impact" id="8af8e0df-7e31-4229-8e49-54b1487fd7e4" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are test settings for Trace and Test Impact.</Description>
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>

View file

@ -24,6 +24,7 @@ namespace UnitTests
public class ItemManagerTest
{
public static IDbConnection DB;
public static ItemManager manager;
[TestInitialize]
public void Initialize()
{
@ -32,33 +33,12 @@ namespace UnitTests
DB = new SqliteConnection(string.Format("uri=file://{0},Version=3", "tshock.test.sqlite"));
DB.Open();
/*try
{
var hostport = Config.MySqlHost.Split(':');
DB = new MySqlConnection();
DB.ConnectionString = String.Format("Server='{0}'; Port='{1}'; Database='{2}'; Uid='{3}'; Pwd='{4}';",
hostport[0],
hostport.Length > 1 ? hostport[1] : "3306",
Config.MySqlDbName,
Config.MySqlUsername,
Config.MySqlPassword
);
DB.Open();
}
catch (MySqlException ex)
{
Log.Error(ex.ToString());
throw new Exception("MySql not setup correctly");
}*/
manager = new ItemManager(DB);
}
[TestMethod]
public void SQLiteItemTest_AddBan()
{
//
// TODO: Add test logic here
//
ItemManager manager = new ItemManager(DB);
Assert.IsNotNull(manager);
Assert.IsFalse( manager.ItemIsBanned("Dirt Block"), "Item isn't banned" );
manager.AddNewBan("Dirt Block");
@ -74,10 +54,7 @@ namespace UnitTests
[TestMethod]
public void SQLiteItemTest_RemoveBan()
{
//
// TODO: Add test logic here
//
ItemManager manager = new ItemManager(DB);
manager = new ItemManager(DB);
Assert.IsNotNull(manager);
Assert.AreEqual(2, manager.ItemBans.Count);
manager.AddNewBan("Dirt Block");

View file

@ -29,51 +29,91 @@ namespace UnitTests
DB.Open();
manager = new RegionManager(DB);
manager.ReloadForUnitTest("test");
}
[TestMethod]
public void AddRegion()
{
Region r = new Region( new Rectangle(100,100,100,100), "test", 0, "test world");
Assert.IsTrue(manager.AddRegion(r.RegionArea.X, r.RegionArea.Y, r.RegionArea.Width, r.RegionArea.Height, r.RegionName, r.RegionWorldID));
Region r = new Region( new Rectangle(100,100,100,100), "test", true, "test");
Assert.IsTrue(manager.AddRegion(r.Area.X, r.Area.Y, r.Area.Width, r.Area.Height, r.Name, r.WorldID));
Assert.AreEqual(1, manager.Regions.Count);
Assert.IsNotNull(manager.getRegion("test"));
Region r2 = new Region(new Rectangle(201, 201, 100, 100), "test2", 0, "test world");
manager.AddRegion(r2.RegionArea.X, r2.RegionArea.Y, r2.RegionArea.Width, r2.RegionArea.Height, r2.RegionName, r2.RegionWorldID);
Region r2 = new Region(new Rectangle(201, 201, 100, 100), "test2", true, "test");
manager.AddRegion(r2.Area.X, r2.Area.Y, r2.Area.Width, r2.Area.Height, r2.Name, r2.WorldID);
Assert.AreEqual(2, manager.Regions.Count);
Assert.IsNotNull(manager.getRegion("test2"));
}
[TestMethod]
public void DeleteRegion()
{
Assert.IsTrue(2 == manager.Regions.Count);
Assert.IsTrue(manager.DeleteRegion("test"));
Assert.IsTrue(1 == manager.Regions.Count);
Assert.IsTrue(manager.DeleteRegion("test2"));
Assert.AreEqual(0, manager.Regions.Count);
Assert.IsTrue(0 == manager.Regions.Count);
}
[TestMethod]
public void InRegion()
{
//
// TODO: Add test logic here
//
Assert.IsTrue(manager.InArea(100, 100));
Assert.IsTrue(manager.InArea(150, 150));
Assert.IsTrue(manager.InArea(200, 200));
Assert.IsTrue(manager.InArea(201, 201));
Assert.IsTrue(manager.InArea(251, 251));
Assert.IsTrue(manager.InArea(301, 301));
Assert.IsFalse(manager.InArea(311, 311));
Assert.IsFalse(manager.InArea(99, 99));
}
[TestMethod]
public void TestMethod2()
public void SetRegionState()
{
//
// TODO: Add test logic here
//
Assert.IsTrue(manager.getRegion("test").DisableBuild);
manager.SetRegionStateTest("test", "test", false);
Assert.IsTrue(!manager.getRegion("test").DisableBuild);
manager.SetRegionStateTest("test", "test", true);
Assert.IsTrue(manager.getRegion("test").DisableBuild);
Assert.IsTrue(manager.getRegion("test2").DisableBuild);
manager.SetRegionStateTest("test2", "test", false);
Assert.IsTrue(!manager.getRegion("test2").DisableBuild);
manager.SetRegionStateTest("test2", "test", true);
Assert.IsTrue(manager.getRegion("test2").DisableBuild);
}
[TestMethod]
public void TestMethod3()
public void CanBuild()
{
//
// TODO: Add test logic here
//
/**
* For now, this test is useless. Need to implement user groups so we can alter Canbuild permission.
*/
TSPlayer t = new TSPlayer(0);
Assert.IsFalse( manager.CanBuild( 100,100,t) );
}
[TestMethod]
public void AddUser()
{
/**
* For now, this test is useless. Need to implement users so we have names to get ids from.
*/
}
[TestMethod]
public void ListID()
{
Assert.IsTrue(RegionManager.ListIDs("1,2,3,4,5").Count == 5);
Assert.IsTrue(RegionManager.ListIDs("").Count == 0);
}
[TestMethod]
public void ListRegions()
{
//needs a little more work.
}
[TestCleanup]

View file

@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<OrderedTest name="RegionManagerTest" storage="c:\users\virus\git\tshock\unittests\regionmanagertest.orderedtest" id="7601a790-d2fb-45d2-a612-1ae4de84eb61" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<OrderedTest name="regionmanagertest" storage="c:\users\virus\git\tshock\unittests\regionmanagertest.orderedtest" id="7601a790-d2fb-45d2-a612-1ae4de84eb61" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Execution id="e2bb6bb7-7bc7-43d5-bb81-e2d13d377599" />
<TestLinks>
<TestLink id="8d92e80b-8c9d-7a14-5c3a-eba6790be784" name="AddRegion" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="a8d03dce-530d-a255-9115-3b783c8a973c" name="DeleteRegion" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="57686a56-2684-8c17-1564-ed9a3c37b167" name="InRegion" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="c77a874e-5605-7aec-f487-110deaa7fafb" name="TestMethod2" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="521a8e25-1f75-066f-b839-56fee4f2a1b1" name="TestMethod3" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="05a473bf-6457-6122-6150-b1aa82e8f869" name="SetRegionState" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="999dec4b-8a9b-3d06-02fb-622ecb449e82" name="CanBuild" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="80e781d1-fd68-212a-9099-8791ad55ed9f" name="AddUser" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="dc9d05c0-db88-716a-bbe0-aff585f7681d" name="ListID" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="e13e8546-b310-71c3-e068-1ecd18bfec8f" name="ListRegions" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<TestLink id="a8d03dce-530d-a255-9115-3b783c8a973c" name="DeleteRegion" storage="bin\release\unittests.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</TestLinks>
</OrderedTest>