Use better command argument parsing

This commit is contained in:
UnknownShadow200 2017-02-25 23:26:56 +11:00
parent 0e009fba81
commit 254fd82de5
14 changed files with 71 additions and 106 deletions

View File

@ -101,7 +101,7 @@ namespace MCGalaxy.Commands.CPE {
if (args != null && args.Length > 1) int.TryParse(args[1], out offset); if (args != null && args.Length > 1) int.TryParse(args[1], out offset);
CustomColor[] cols = Colors.ExtColors; CustomColor[] cols = Colors.ExtColors;
for( int i = 0; i < cols.Length; i++ ) { for (int i = 0; i < cols.Length; i++) {
CustomColor col = cols[i]; CustomColor col = cols[i];
if (col.Undefined) continue; if (col.Undefined) continue;

View File

@ -72,7 +72,7 @@ namespace MCGalaxy.Commands.CPE {
int targetId; int targetId;
if (parts.Length >= 2 ) { if (parts.Length >= 2 ) {
string id = parts[1]; string id = parts[1];
if (!CheckBlockId(p, id, global, out targetId)) return; if (!CheckBlockId(p, id, out targetId)) return;
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition def = defs[targetId]; BlockDefinition def = defs[targetId];
@ -105,8 +105,8 @@ namespace MCGalaxy.Commands.CPE {
static void CopyHandler(Player p, string[] parts, bool global, string cmd) { static void CopyHandler(Player p, string[] parts, bool global, string cmd) {
if (parts.Length <= 2) { Help(p, cmd); return; } if (parts.Length <= 2) { Help(p, cmd); return; }
int srcId, dstId; int srcId, dstId;
if (!CheckBlockId(p, parts[1], global, out srcId)) return; if (!CheckBlockId(p, parts[1], out srcId)) return;
if (!CheckBlockId(p, parts[2], global, out dstId)) return; if (!CheckBlockId(p, parts[2], out dstId)) return;
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition src = defs[srcId], dst = defs[dstId]; BlockDefinition src = defs[srcId], dst = defs[dstId];
@ -128,7 +128,7 @@ namespace MCGalaxy.Commands.CPE {
static void InfoHandler(Player p, string[] parts, bool global, string cmd) { static void InfoHandler(Player p, string[] parts, bool global, string cmd) {
if (parts.Length == 1) { Help(p, cmd); return; } if (parts.Length == 1) { Help(p, cmd); return; }
int id; int id;
if (!CheckBlockId(p, parts[1], global, out id)) return; if (!CheckBlockId(p, parts[1], out id)) return;
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition def = defs[id]; BlockDefinition def = defs[id];
@ -179,7 +179,7 @@ namespace MCGalaxy.Commands.CPE {
static void RemoveHandler(Player p, string[] parts, bool global, string cmd) { static void RemoveHandler(Player p, string[] parts, bool global, string cmd) {
if (parts.Length <= 1) { Help(p, cmd); return; } if (parts.Length <= 1) { Help(p, cmd); return; }
int id; int id;
if (!CheckBlockId(p, parts[1], global, out id)) return; if (!CheckBlockId(p, parts[1], out id)) return;
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition def = defs[id]; BlockDefinition def = defs[id];
@ -213,22 +213,22 @@ namespace MCGalaxy.Commands.CPE {
bd.Name = value; bd.Name = value;
step++; step++;
} else if (step == 3) { } else if (step == 3) {
if (CommandParser.GetBool(p, value, ref temp)) { if (CommandParser.GetBool(p, value, ref temp)) {
bd.Shape = temp ? (byte)0 : (byte)16; bd.Shape = temp ? (byte)0 : (byte)16;
step++; step++;
} }
} else if (step == 4) { } else if (step == 4) {
if (byte.TryParse(value, out bd.TopTex)) { if (CommandParser.GetByte(p, value, "Texture ID", ref bd.TopTex)) {
step += (bd.Shape == 0 ? 5 : 1); // skip other texture steps for sprites step += (bd.Shape == 0 ? 5 : 1); // skip other texture steps for sprites
if (bd.Shape == 0) bd.SetAllTex(bd.TopTex); if (bd.Shape == 0) bd.SetAllTex(bd.TopTex);
} }
} else if (step == 5) { } else if (step == 5) {
if (byte.TryParse(value, out bd.SideTex)) { if (CommandParser.GetByte(p, value, "Texture ID", ref bd.SideTex)) {
bd.SetSideTex(bd.SideTex); bd.SetSideTex(bd.SideTex);
step++; step++;
} }
} else if (step == 6) { } else if (step == 6) {
if (byte.TryParse(value, out bd.BottomTex)) if (CommandParser.GetByte(p, value, "Texture ID", ref bd.BottomTex))
step++; step++;
} else if (step == 7) { } else if (step == 7) {
if (ParseCoords(value, ref bd.MinX, ref bd.MinY, ref bd.MinZ)) if (ParseCoords(value, ref bd.MinX, ref bd.MinY, ref bd.MinZ))
@ -238,10 +238,8 @@ namespace MCGalaxy.Commands.CPE {
step++; step++;
bd.Shape = bd.MaxY; bd.Shape = bd.MaxY;
} else if (step == 9) { } else if (step == 9) {
if (value == "0" || value == "1" || value == "2") { if (CommandParser.GetByte(p, value, "Collide type", ref bd.CollideType, 0, 2))
bd.CollideType = byte.Parse(value);
step++; step++;
}
} else if (step == 10) { } else if (step == 10) {
if (Utils.TryParseDecimal(value, out bd.Speed) && bd.Speed >= 0.25f && bd.Speed <= 3.96f) if (Utils.TryParseDecimal(value, out bd.Speed) && bd.Speed >= 0.25f && bd.Speed <= 3.96f)
step++; step++;
@ -251,21 +249,18 @@ namespace MCGalaxy.Commands.CPE {
step++; step++;
} }
} else if (step == 12) { } else if (step == 12) {
bool result = byte.TryParse(value, out bd.WalkSound); if (CommandParser.GetByte(p, value, "Walk sound", ref bd.CollideType, 0, 11))
if (result && bd.WalkSound <= 11)
step++; step++;
} else if (step == 13) { } else if (step == 13) {
if (CommandParser.GetBool(p, value, ref temp)) { if (CommandParser.GetBool(p, value, ref bd.FullBright))
bd.FullBright = temp;
step++; step++;
}
} else if (step == 14) { } else if (step == 14) {
bool result = byte.TryParse(value, out bd.BlockDraw); if (CommandParser.GetByte(p, value, "Block draw", ref bd.BlockDraw, 0, 4))
if (result && bd.BlockDraw >= 0 && bd.BlockDraw <= 4)
step++; step++;
} else if (step == 15) { } else if (step == 15) {
if (byte.TryParse(value, out bd.FogDensity)) if (CommandParser.GetByte(p, value, "Fog density", ref bd.FogDensity)) {
step += (bd.FogDensity == 0 ? 2 : 1); step += (bd.FogDensity == 0 ? 2 : 1);
}
} else if (step == 16) { } else if (step == 16) {
if (Utils.CheckHex(p, ref value)) { if (Utils.CheckHex(p, ref value)) {
CustomColor rgb = Colors.ParseHex(value); CustomColor rgb = Colors.ParseHex(value);
@ -299,7 +294,7 @@ namespace MCGalaxy.Commands.CPE {
return; return;
} }
int blockId; int blockId;
if (!CheckBlockId(p, parts[1], global, out blockId)) return; if (!CheckBlockId(p, parts[1], out blockId)) return;
BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs; BlockDefinition[] defs = global ? BlockDefinition.GlobalDefs : p.level.CustomBlockDefs;
BlockDefinition def = defs[blockId]; BlockDefinition def = defs[blockId];
@ -540,13 +535,12 @@ namespace MCGalaxy.Commands.CPE {
static bool EditByte(Player p, string value, string propName, ref byte target, static bool EditByte(Player p, string value, string propName, ref byte target,
int step, int offset, byte min, byte max) { int step, int offset, byte min, byte max) {
int temp = 0; int temp = 0;
if (!int.TryParse(value, out temp) || temp < min || temp > max) { if (!CommandParser.GetInt(p, value, propName, ref temp, min, max)) {
Player.Message(p, propName + " must be an integer between {0} and {1}.", min, max);
if (step != -1) SendEditHelp(p, step, offset); if (step != -1) SendEditHelp(p, step, offset);
return false; return false;
} }
target = (byte)temp;
return true; target = (byte)temp; return true;
} }
static bool ParseCoords(string parts, ref byte x, ref byte y, ref byte z) { static bool ParseCoords(string parts, ref byte x, ref byte y, ref byte z) {
@ -562,14 +556,9 @@ namespace MCGalaxy.Commands.CPE {
return true; return true;
} }
static bool CheckBlockId(Player p, string arg, bool global, out int blockId) { static bool CheckBlockId(Player p, string arg, out int blockId) {
if (!int.TryParse(arg, out blockId)) { blockId = 0;
Player.Message(p, "&cProvided block id is not a number."); return false; return CommandParser.GetInt(p, arg, "Block ID", ref blockId, 0, 254);
}
if (blockId <= 0 || blockId >= Block.Invalid) {
Player.Message(p, "&cBlock id must be between 1-254"); return false;
}
return true;
} }

View File

@ -67,9 +67,8 @@ namespace MCGalaxy.Commands {
else Player.Message(p, "Deleted message."); else Player.Message(p, "Deleted message.");
} }
} else { } else {
int num; int num = 0;
if (!int.TryParse(message, out num)) { Player.Message(p, "Incorrect number given."); return; } if (!CommandParser.GetInt(p, message, "Message number", ref num, 0)) return;
if (num < 0) { Player.Message(p, "Message number must be greater than or equal to 0."); return; }
using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) { using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) {
if (num >= Inbox.Rows.Count) { if (num >= Inbox.Rows.Count) {

View File

@ -46,24 +46,34 @@ namespace MCGalaxy {
} }
if (value < min || value > max) { if (value < min || value > max) {
Player.Message(p, "{2} must be between {0} and {1}", min, max, type); return false; // Try to provide more helpful range messages
if (max == int.MaxValue) {
Player.Message(p, "{0} must be {1} or greater", type, min);
} else if (min == int.MinValue) {
Player.Message(p, "{0} must be {1} or less", type, max);
} else {
Player.Message(p, "{0} must be between {1} and {2}", type, min, max);
}
return false;
} }
result = value; return true; result = value; return true;
} }
/// <summary> Attempts to parse the given argument as an byte, returning whether that succeeded. </summary> /// <summary> Attempts to parse the given argument as an byte, returning whether that succeeded. </summary>
public static bool GetByte(Player p, string input, string type, ref byte result) { public static bool GetByte(Player p, string input, string type, ref byte result,
byte min = byte.MinValue, byte max = byte.MaxValue) {
int temp = 0; int temp = 0;
if (!GetInt(p, input, type, ref temp, byte.MinValue, byte.MaxValue)) return false; if (!GetInt(p, input, type, ref temp, min, max)) return false;
result = (byte)temp; return true; result = (byte)temp; return true;
} }
/// <summary> Attempts to parse the given argument as an byte, returning whether that succeeded. </summary> /// <summary> Attempts to parse the given argument as an byte, returning whether that succeeded. </summary>
public static bool GetUShort(Player p, string input, string type, ref ushort result) { public static bool GetUShort(Player p, string input, string type, ref ushort result,
ushort min = ushort.MinValue, ushort max = ushort.MaxValue) {
int temp = 0; int temp = 0;
if (!GetInt(p, input, type, ref temp, ushort.MinValue, ushort.MaxValue)) return false; if (!GetInt(p, input, type, ref temp, min, max)) return false;
result = (ushort)temp; return true; result = (ushort)temp; return true;
} }

View File

@ -34,10 +34,10 @@ namespace MCGalaxy.Commands {
Player who = PlayerInfo.FindMatches(p, args[0]); Player who = PlayerInfo.FindMatches(p, args[0]);
if (who == null) return; if (who == null) return;
byte amount = 0; byte amount = 0;
if (!byte.TryParse(args[1], out amount)) { if (!CommandParser.GetByte(p, args[1], "Bounty amount", ref amount)) return;
Player.Message(p, "The bounty amount must be an positive integer less than 256."); return;
}
if (p.money < amount) { if (p.money < amount) {
Player.Message(p, "You do not have enough " + Server.moneys + " to place such a large bountry."); return; Player.Message(p, "You do not have enough " + Server.moneys + " to place such a large bountry."); return;
} }

View File

@ -78,9 +78,8 @@ namespace MCGalaxy.Commands {
if (args.Length == 2) { if (args.Length == 2) {
int rounds = 1; int rounds = 1;
if (!int.TryParse(args[1], out rounds)) { if (!CommandParser.GetInt(p, args[1], "Rounds", ref rounds, 0)) return;
Player.Message(p, "You need to specify a valid option!"); return;
}
ZombieGameStatus status = rounds == 0 ? ZombieGameStatus status = rounds == 0 ?
ZombieGameStatus.InfiniteRounds : ZombieGameStatus.VariableRounds; ZombieGameStatus.InfiniteRounds : ZombieGameStatus.VariableRounds;
Server.zombie.Start(status, lvl, rounds); Server.zombie.Start(status, lvl, rounds);

View File

@ -119,29 +119,16 @@ namespace MCGalaxy.Commands {
static int ParseLimit(Player p, string[] args) { static int ParseLimit(Player p, string[] args) {
int limit = 0; int limit = 0;
string limitArg = args[args.Length - 1]; string limitArg = args[args.Length - 1];
if (!Int32.TryParse(limitArg, out limit)) {
Player.Message(p, "&c\"{0}\" is not an integer.", limitArg); return -1;
}
if (limit < 1) { if (!CommandParser.GetInt(p, args[1], "Limit", ref limit, 1, 15)) return -1;
Player.Message(p, "&c\"{0}\" is too small, the min limit is 1.", limitArg); return -1;
}
if (limit > 15) {
Player.Message(p, "&c\"{0}\" is too large, the max limit is 15.", limitArg); return -1;
}
return limit; return limit;
} }
static int ParseOffset(Player p, string[] args) { static int ParseOffset(Player p, string[] args) {
if (args.Length <= 2) return 0; if (args.Length <= 2) return 0;
int offset = 0; int offset = 0;
if (!Int32.TryParse(args[1], out offset)) {
Player.Message(p, "&c\"{0}\" is not an integer.", args[1]); return -1; if (!CommandParser.GetInt(p, args[1], "Offset", ref offset, 0)) return -1;
}
if (offset < 0) {
Player.Message(p, "&cOffset must be greater than or equal to 0.", args[1]); return -1;
}
return offset; return offset;
} }

View File

@ -29,12 +29,10 @@ namespace MCGalaxy.Commands {
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
string[] args = message.Split(' '); string[] args = message.Split(' ');
if (message == "") { Help(p); return; } if (message == "") { Help(p); return; }
int limit = 0;
bool hasLimit = args.Length > 1;
if (hasLimit && (!int.TryParse(args[1], out limit) || limit <= 0)) { int limit = 0;
Player.Message(p, "Limit amount must be a whole number and greater than 0."); return; bool hasLimit = args.Length > 1;
} if (hasLimit && !CommandParser.GetInt(p, args[1], "Limit", ref limit, 1)) return;
switch (args[0].ToLower()) { switch (args[0].ToLower()) {
case "rt": case "rt":

View File

@ -34,13 +34,9 @@ namespace MCGalaxy.Commands
Server.PositionInterval = 2000; Server.PositionInterval = 2000;
Chat.MessageAll("&dLow lag %Sturned &aON %S- positions update every &b2000 %Sms."); Chat.MessageAll("&dLow lag %Sturned &aON %S- positions update every &b2000 %Sms.");
} else { } else {
int interval; int interval = 0;
if (!int.TryParse(message, out interval)) { if (!CommandParser.GetInt(p, message, "Interval", ref interval, 20, 2000)) return;
Player.Message(p, "Interval given must be an integer."); return;
}
if (interval < 20 || interval > 2000) {
Player.Message(p, "Interval must be between 20 and 2000 milliseconds."); return;
}
Server.PositionInterval = interval; Server.PositionInterval = interval;
Chat.MessageAll("Positions now update every &b{0} %Smilliseconds.", interval); Chat.MessageAll("Positions now update every &b{0} %Smilliseconds.", interval);
} }

View File

@ -49,8 +49,7 @@ namespace MCGalaxy.Commands.World {
} }
} }
static Level LoadLevelCore(Player p, string name, static Level LoadLevelCore(Player p, string name, string physStr, bool autoLoaded) {
string phys, bool autoLoaded) {
Level[] loaded = LevelInfo.Loaded.Items; Level[] loaded = LevelInfo.Loaded.Items;
foreach (Level l in loaded) { foreach (Level l in loaded) {
if (l.name == name) { Player.Message(p, "Level {0} %Sis already loaded.", l.ColoredName); return null; } if (l.name == name) { Player.Message(p, "Level {0} %Sis already loaded.", l.ColoredName); return null; }
@ -71,11 +70,10 @@ namespace MCGalaxy.Commands.World {
if (!autoLoaded) if (!autoLoaded)
Chat.MessageWhere("Level {0} %Sloaded.", pl => Entities.CanSee(pl, p), lvl.ColoredName); Chat.MessageWhere("Level {0} %Sloaded.", pl => Entities.CanSee(pl, p), lvl.ColoredName);
int physLevel; int phys = 0;
if (!int.TryParse(phys, out physLevel)) { if (!CommandParser.GetInt(p, physStr, "Physics state", ref phys, 0, 5)) return lvl;
Player.Message(p, "Physics must be an integer between 0 and 5."); return lvl;
} if (phys >= 1 && phys <= 5) lvl.setPhysics(phys);
if (physLevel >= 1 && physLevel <= 5) lvl.setPhysics(physLevel);
return lvl; return lvl;
} }

View File

@ -39,11 +39,11 @@ namespace MCGalaxy.Commands.World {
if (args.Length < 5 || args.Length > 6) { Help(p); return false; } if (args.Length < 5 || args.Length > 6) { Help(p); return false; }
if (!MapGen.IsRecognisedTheme(args[4])) { MapGen.PrintThemes(p); return false; } if (!MapGen.IsRecognisedTheme(args[4])) { MapGen.PrintThemes(p); return false; }
ushort x, y, z; ushort x = 0, y = 0, z = 0;
string name = args[0].ToLower(); string name = args[0].ToLower();
if (!UInt16.TryParse(args[1], out x) || !UInt16.TryParse(args[2], out y) || !UInt16.TryParse(args[3], out z)) { if (!CommandParser.GetUShort(p, args[1], "Width", ref x)) return false;
Player.Message(p, "Invalid dimensions."); return false; if (!CommandParser.GetUShort(p, args[2], "Height", ref y)) return false;
} if (!CommandParser.GetUShort(p, args[3], "Length", ref z)) return false;
string seed = args.Length == 6 ? args[5] : ""; string seed = args.Length == 6 ? args[5] : "";
if (!MapGen.OkayAxis(x)) { Player.Message(p, "width must be divisible by 16, and >= 16"); return false; } if (!MapGen.OkayAxis(x)) { Player.Message(p, "width must be divisible by 16, and >= 16"); return false; }

View File

@ -32,13 +32,8 @@ namespace MCGalaxy.Commands {
string[] args = message.Split(' '); string[] args = message.Split(' ');
Level level = p != null ? p.level : Server.mainLevel; Level level = p != null ? p.level : Server.mainLevel;
int state = 0, stateIndex = args.Length == 1 ? 0 : 1; int state = 0, stateIndex = args.Length == 1 ? 0 : 1;
if (!int.TryParse(args[stateIndex], out state)) { if (!CommandParser.GetInt(p, args[stateIndex], "Physics state", ref state, 0, 5)) return;
Player.Message(p, "Given physics state was not a proper number."); return;
}
if (state < 0 || state > 5 ) {
Player.Message(p, "Given physics state was less than 0, or greater than 5."); return;
}
if (args.Length == 2) { if (args.Length == 2) {
level = Matcher.FindLevels(p, args[0]); level = Matcher.FindLevels(p, args[0]);

View File

@ -43,10 +43,10 @@ namespace MCGalaxy.Commands.World {
Level lvl = Matcher.FindLevels(p, args[0]); Level lvl = Matcher.FindLevels(p, args[0]);
if (lvl == null) return true; if (lvl == null) return true;
ushort x, y, z; ushort x = 0, y = 0, z = 0;
if (!UInt16.TryParse(args[1], out x) || !UInt16.TryParse(args[2], out y) || !UInt16.TryParse(args[3], out z)) { if (!CommandParser.GetUShort(p, args[1], "Width", ref x)) return true;
Player.Message(p, "Invalid dimensions."); return true; if (!CommandParser.GetUShort(p, args[2], "Height", ref y)) return true;
} if (!CommandParser.GetUShort(p, args[3], "Length", ref z)) return true;
if (!MapGen.OkayAxis(x)) { Player.Message(p, "width must be divisible by 16, and >= 16"); return true; } if (!MapGen.OkayAxis(x)) { Player.Message(p, "width must be divisible by 16, and >= 16"); return true; }
if (!MapGen.OkayAxis(y)) { Player.Message(p, "height must be divisible by 16, and >= 16"); return true; } if (!MapGen.OkayAxis(y)) { Player.Message(p, "height must be divisible by 16, and >= 16"); return true; }

View File

@ -75,15 +75,9 @@ namespace MCGalaxy.Commands {
static bool ParseCoord(Player p, string arg, int cur, string axis, out int value) { static bool ParseCoord(Player p, string arg, int cur, string axis, out int value) {
bool relative = arg[0] == '~'; bool relative = arg[0] == '~';
if (relative) arg = arg.Substring(1); if (relative) arg = arg.Substring(1);
value = 0;
if (!int.TryParse(arg, out value)) { if (!CommandParser.GetInt(p, arg, axis + " coordinate", ref value, -1024, 1024)) return false;
Player.Message(p, axis + " coordinate must be an integer from -1024 to 1024."); return false;
}
if (value < -1024 || value > 1024) {
Player.Message(p, axis + " coordinate must be between -1024 to 1024."); return false;
}
if (relative) value += (cur / 32); if (relative) value += (cur / 32);
return true; return true;
} }