diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs
index 7fab1b5c..62a967c3 100755
--- a/TShockAPI/Commands.cs
+++ b/TShockAPI/Commands.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Net;
@@ -22,13 +23,19 @@ namespace TShockAPI
public int PlayerX;
public int PlayerY;
public int PlayerID;
+ ///
+ /// Parameters passed to the arguement. Does not include the command name.
+ /// IE '/kick "jerk face"' will only have 1 argument
+ ///
+ public List Parameters;
- public CommandArgs(string message, int x, int y, int id)
+ public CommandArgs(string message, int x, int y, int id, List args)
{
Message = message;
PlayerX = x;
PlayerY = y;
PlayerID = id;
+ Parameters = args;
}
}
@@ -45,7 +52,7 @@ namespace TShockAPI
command = cmd;
}
- public bool Run(string msg, TSPlayer ply)
+ public bool Run(string msg, TSPlayer ply, List parms)
{
if (!ply.group.HasPermission(permission))
{
@@ -57,6 +64,7 @@ namespace TShockAPI
args.PlayerX = (int)ply.GetPlayer().position.X;
args.PlayerY = (int)ply.GetPlayer().position.Y;
args.PlayerID = ply.GetPlayerID();
+ args.Parameters = parms;
command(args);
return true;
@@ -77,6 +85,88 @@ namespace TShockAPI
}
}
+ ///
+ /// Parses a string of parameters into a list. Handles quotes.
+ ///
+ ///
+ ///
+ public static List ParseParameters(string str)
+ {
+ var ret = new List();
+ var sb = new StringBuilder();
+ bool instr = false;
+ for (int i = 0; i < str.Length; i++)
+ {
+ char c = str[i];
+
+ if (instr)
+ {
+ if (c == '\\')
+ {
+ if (i + 1 >= str.Length)
+ break;
+ c = GetEscape(str[++i]);
+ }
+ else if (c == '"')
+ {
+ ret.Add(sb.ToString());
+ sb.Clear();
+ instr = false;
+ continue;
+ }
+ sb.Append(c);
+ }
+ else
+ {
+ if (IsWhiteSpace(c))
+ {
+ if (sb.Length > 0)
+ {
+ ret.Add(sb.ToString());
+ sb.Clear();
+ }
+ }
+ else if (c == '"')
+ {
+ if (sb.Length > 0)
+ {
+ ret.Add(sb.ToString());
+ sb.Clear();
+ }
+ instr = true;
+ }
+ else
+ {
+ sb.Append(c);
+ }
+ }
+ }
+ if (sb.Length > 0)
+ ret.Add(sb.ToString());
+
+ return ret;
+ }
+
+ static char GetEscape(char c)
+ {
+ switch (c)
+ {
+ case '\\':
+ return '\\';
+ case '"':
+ return '"';
+ case 't':
+ return '\t';
+ default:
+ return c;
+ }
+ }
+
+ static bool IsWhiteSpace(char c)
+ {
+ return c == ' ' || c == '\t' || c == '\n';
+ }
+
public static void InitCommands()
{
commands.Add(new Command("kick", "kick", Kick));
@@ -210,110 +300,113 @@ namespace TShockAPI
{
int player = Tools.FindPlayer(plStr);
if (player == -1)
- Tools.SendMessage(ply, "Invalid player!", 255f, 0f, 0f);
+ Tools.SendMessage(ply, "Invalid player!", Color.Red);
else if (player == -2)
- Tools.SendMessage(ply, "More than one player matched!", 255f, 0f, 0f );
+ Tools.SendMessage(ply, "More than one player matched!", Color.Red);
else
{
if (!Tools.Kick(player, reason.Length != 0 ? reason : "Misbehaviour."))
{
- Tools.SendMessage(ply, "You can't kick another admin!", 255f, 0f, 0f );
+ Tools.SendMessage(ply, "You can't kick another admin!", Color.Red);
}
}
}
else
- Tools.SendMessage(ply, "Invalid syntax! Proper syntax: /kick [reason]",
- 255f, 0f, 0f );
+ Tools.SendMessage(ply, "Invalid syntax! Proper syntax: /kick [reason]", Color.Red);
}
public static void BanIP(CommandArgs args)
{
- if (args.Message.Split(' ').Length == 2)
+ int ply = args.PlayerID;
+
+ if (args.Parameters.Count < 1)
{
- string ip = args.Message.Split(' ')[1];
- TShock.Bans.AddBan(ip, "", "Manually added IP address ban.");
- }
- else if (args.Message.Split(' ').Length > 2)
- {
- string reason = "";
- for (int i = 2; i > args.Message.Split(' ').Length; i++)
- {
- reason += args.Message.Split(' ')[i];
- }
- string ip = args.Message.Split(' ')[1];
- TShock.Bans.AddBan(ip, "", reason);
- }
- else
- {
- Tools.SendMessage(args.PlayerID, "Syntax: /banip ");
+ Tools.SendMessage(ply, "Syntax: /banip [reason]", Color.Red);
+ return;
}
+
+ string ip = args.Parameters[0];
+ string reason = args.Parameters.Count > 1 ? args.Parameters[1] : "Manually added IP address ban.";
+
+ TShock.Bans.AddBan(ip, "", reason);
}
public static void Ban(CommandArgs args)
{
- string input = args.Message.Remove(0, 4).Trim();
- string plStr = "";
- string reason = "";
- int splitIndex = input.StartsWith("\"") ? splitIndex = input.IndexOf('"', 1) : splitIndex = input.IndexOf(' ', 0);
- if (splitIndex == -1)
- {
- plStr = input;
- }
- else
- {
- plStr = input.Substring(0, splitIndex).Trim().TrimEnd('"').TrimStart('"');
- reason = input.Substring(splitIndex + 1).Trim().TrimEnd('"').TrimStart('"');
- }
int ply = args.PlayerID;
+
+ if (args.Parameters.Count < 1)
+ {
+ Tools.SendMessage(ply, "Missing player name", Color.Red);
+ return;
+ }
+
+ string plStr = args.Parameters[0];
+ string reason = args.Parameters.Count > 1 ? args.Parameters[1] : "Misbehaviour";
+
+
if (plStr.Length != 0)
{
int player = Tools.FindPlayer(plStr);
if (player == -1)
- Tools.SendMessage(ply, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "Invalid player!", Color.Red);
else if (player == -2)
- Tools.SendMessage(ply, "More than one player matched!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "More than one player matched!", Color.Red);
else
{
- if (!Tools.Ban(player, reason.Length != 0 ? reason : "Misbehaviour."))
+ if (!Tools.Ban(player, reason))
{
- Tools.SendMessage(ply, "You can't ban another admin!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "You can't ban another admin!", Color.Red);
}
}
}
else
- Tools.SendMessage(ply, "Invalid syntax! Proper syntax: /ban [reason]",
- new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "Invalid syntax! Proper syntax: /ban [reason]", Color.Red);
}
public static void UnBan(CommandArgs args)
{
- string plStr = args.Message.Remove(0, 7);
int adminplr = args.PlayerID;
+ if (args.Parameters.Count < 1)
+ {
+ Tools.SendMessage(adminplr, "Missing player name", Color.Red);
+ return;
+ }
+
+ string plStr = args.Parameters[0];
+
var ban = TShock.Bans.GetBanByName(plStr);
if (ban != null)
{
TShock.Bans.RemoveBan(ban);
- Tools.SendMessage(adminplr, string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), new[] { 255f, 0f, 0f });
+ Tools.SendMessage(adminplr, string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
}
else
{
- Tools.SendMessage(adminplr, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(adminplr, "Invalid player!", Color.Red);
}
}
public static void UnBanIP(CommandArgs args)
{
- string plStr = args.Message.Remove(0, 9);
int adminplr = args.PlayerID;
+ if (args.Parameters.Count < 1)
+ {
+ Tools.SendMessage(adminplr, "Missing ip", Color.Red);
+ return;
+ }
+
+ string plStr = args.Parameters[0];
+
var ban = TShock.Bans.GetBanByIp(plStr);
if (ban != null)
{
TShock.Bans.RemoveBan(ban);
- Tools.SendMessage(adminplr, string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), new[] { 255f, 0f, 0f });
+ Tools.SendMessage(adminplr, string.Format("Unbanned {0} ({1})!", ban.Name, ban.IP), Color.Red);
}
else
{
- Tools.SendMessage(adminplr, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(adminplr, "Invalid player!", Color.Red);
}
}
@@ -490,7 +583,7 @@ namespace TShockAPI
Tools.SendMessage(ply, "Teleported to " + player);
}
else
- Tools.SendMessage(ply, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "Invalid player!", Color.Red);
}
public static void TPHere(CommandArgs args)
@@ -504,7 +597,7 @@ namespace TShockAPI
Tools.SendMessage(ply, "You brought " + player + " here.");
}
else
- Tools.SendMessage(ply, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(ply, "Invalid player!", Color.Red);
}
public static void SpawnMob(CommandArgs args)
@@ -536,7 +629,7 @@ namespace TShockAPI
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /spawnmob [amount]",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
public static void Item(CommandArgs args)
@@ -572,14 +665,14 @@ namespace TShockAPI
}
}
if (!flag)
- Tools.SendMessage(args.PlayerID, "You don't have free slots!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "You don't have free slots!", Color.Red);
}
else
- Tools.SendMessage(args.PlayerID, "Invalid item type!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid item type!", Color.Red);
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /item - ",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
public static void Give(CommandArgs args)
@@ -623,17 +716,17 @@ namespace TShockAPI
}
}
if (!flag)
- Tools.SendMessage(args.PlayerID, "Player does not have free slots!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Player does not have free slots!", Color.Red);
}
else
- Tools.SendMessage(args.PlayerID, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid player!", Color.Red);
}
else
- Tools.SendMessage(args.PlayerID, "Invalid item type!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid item type!", Color.Red);
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /give
- ",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
public static void Heal(CommandArgs args)
@@ -784,11 +877,11 @@ namespace TShockAPI
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /time ",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /time ",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
public static void Kill(CommandArgs args)
@@ -798,9 +891,9 @@ namespace TShockAPI
{
int player = Tools.FindPlayer((msgargs[1].TrimEnd('"')).TrimStart('"'));
if (player == -1)
- Tools.SendMessage(args.PlayerID, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid player!", Color.Red);
else if (player == -2)
- Tools.SendMessage(args.PlayerID, "More than one player matched!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "More than one player matched!", Color.Red);
else
{
Tools.SendMessage(args.PlayerID, "You just killed " + Tools.FindPlayer(player) + "!");
@@ -817,14 +910,14 @@ namespace TShockAPI
msgargs[i] = (msgargs[i].TrimStart('"')).TrimEnd('"');
if (msgargs.Length == 1)
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /slap [dmg]",
- new[] { 255f, 0f, 0f });
+ Color.Red);
else if (msgargs.Length == 2)
{
int player = Tools.FindPlayer(msgargs[1]);
if (player == -1)
- Tools.SendMessage(args.PlayerID, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid player!", Color.Red);
else if (player == -2)
- Tools.SendMessage(args.PlayerID, "More than one player matched!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "More than one player matched!", Color.Red);
else
{
NetMessage.SendData(26, -1, -1, "", player, ((new Random()).Next(1, 20)), 5, (float)0);
@@ -838,9 +931,9 @@ namespace TShockAPI
int damage = 5;
int.TryParse(msgargs[2], out damage);
if (player == -1)
- Tools.SendMessage(args.PlayerID, "Invalid player!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "Invalid player!", Color.Red);
else if (player == -2)
- Tools.SendMessage(args.PlayerID, "More than one player matched!", new[] { 255f, 0f, 0f });
+ Tools.SendMessage(args.PlayerID, "More than one player matched!", Color.Red);
else
{
NetMessage.SendData(26, -1, -1, "", player, ((new Random()).Next(-1, 1)), damage, (float)0);
@@ -850,7 +943,7 @@ namespace TShockAPI
}
else
Tools.SendMessage(args.PlayerID, "Invalid syntax! Proper syntax: /slap [dmg]",
- new[] { 255f, 0f, 0f });
+ Color.Red);
}
public static void ProtectSpawn(CommandArgs args)
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index 08092988..c0aa6df8 100755
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -19,7 +19,7 @@ namespace TShockAPI
public static string saveDir = "./tshock/";
- public static Version VersionNum = new Version(2, 0, 0, 4);
+ public static Version VersionNum = new Version(2, 0, 0, 5);
public static string VersionCodename = "UnrealIRCd ftw (irc.shankshock.com #terraria)";
@@ -294,6 +294,12 @@ namespace TShockAPI
}
bool HandleTile(MemoryStream data, GetDataEventArgs e)
{
+ if (Main.player[e.Msg.whoAmI].dead)
+ {
+ Tools.ForceKick(e.Msg.whoAmI, "Manipulating tiles when dead");
+ return true;
+ }
+
byte type = data.ReadInt8();
int x = data.ReadInt32();
int y = data.ReadInt32();
@@ -442,6 +448,12 @@ namespace TShockAPI
bool HandleLiquidSet(MemoryStream data, GetDataEventArgs e)
{
+ if (Main.player[e.Msg.whoAmI].dead)
+ {
+ Tools.ForceKick(e.Msg.whoAmI, "Manipulating liquids when dead");
+ return true;
+ }
+
int x = data.ReadInt32();
int y = data.ReadInt32();
byte liquid = data.ReadInt8();
@@ -575,11 +587,19 @@ namespace TShockAPI
if (text.StartsWith("/"))
{
- //Commands.CommandArgs args = new Commands.CommandArgs(msg, x, y, ply);
+ text = text.Remove(0, 1);
+
+ var args = Commands.ParseParameters(text);
+ if (args.Count < 1)
+ return;
+
+ string scmd = args[0];
+ args.RemoveAt(0);
+
Commands.Command cmd = null;
for (int i = 0; i < Commands.commands.Count; i++)
{
- if (Commands.commands[i].Name().Equals(text.Split(' ')[0].TrimStart('/')))
+ if (Commands.commands[i].Name().Equals(scmd))
{
cmd = Commands.commands[i];
}
@@ -591,7 +611,7 @@ namespace TShockAPI
}
else
{
- if (!cmd.Run(text, players[ply]))
+ if (!cmd.Run(text, players[ply], args))
{
Tools.SendLogs(Tools.FindPlayer(ply) + " tried to execute " + cmd.Name(), Color.Red);
Tools.SendMessage(ply, "You do not have access to that command.", Color.Red);