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);
CustomColor[] cols = Colors.ExtColors;
for( int i = 0; i < cols.Length; i++ ) {
for (int i = 0; i < cols.Length; i++) {
CustomColor col = cols[i];
if (col.Undefined) continue;

View File

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

View File

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

View File

@ -46,24 +46,34 @@ namespace MCGalaxy {
}
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;
}
/// <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;
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;
}
/// <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;
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;
}

View File

@ -34,10 +34,10 @@ namespace MCGalaxy.Commands {
Player who = PlayerInfo.FindMatches(p, args[0]);
if (who == null) return;
byte amount = 0;
if (!byte.TryParse(args[1], out amount)) {
Player.Message(p, "The bounty amount must be an positive integer less than 256."); return;
}
if (!CommandParser.GetByte(p, args[1], "Bounty amount", ref amount)) return;
if (p.money < amount) {
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) {
int rounds = 1;
if (!int.TryParse(args[1], out rounds)) {
Player.Message(p, "You need to specify a valid option!"); return;
}
if (!CommandParser.GetInt(p, args[1], "Rounds", ref rounds, 0)) return;
ZombieGameStatus status = rounds == 0 ?
ZombieGameStatus.InfiniteRounds : ZombieGameStatus.VariableRounds;
Server.zombie.Start(status, lvl, rounds);

View File

@ -119,29 +119,16 @@ namespace MCGalaxy.Commands {
static int ParseLimit(Player p, string[] args) {
int limit = 0;
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) {
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;
}
if (!CommandParser.GetInt(p, args[1], "Limit", ref limit, 1, 15)) return -1;
return limit;
}
static int ParseOffset(Player p, string[] args) {
if (args.Length <= 2) return 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 (offset < 0) {
Player.Message(p, "&cOffset must be greater than or equal to 0.", args[1]); return -1;
}
if (!CommandParser.GetInt(p, args[1], "Offset", ref offset, 0)) return -1;
return offset;
}

View File

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

View File

@ -34,13 +34,9 @@ namespace MCGalaxy.Commands
Server.PositionInterval = 2000;
Chat.MessageAll("&dLow lag %Sturned &aON %S- positions update every &b2000 %Sms.");
} else {
int interval;
if (!int.TryParse(message, out interval)) {
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;
}
int interval = 0;
if (!CommandParser.GetInt(p, message, "Interval", ref interval, 20, 2000)) return;
Server.PositionInterval = 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,
string phys, bool autoLoaded) {
static Level LoadLevelCore(Player p, string name, string physStr, bool autoLoaded) {
Level[] loaded = LevelInfo.Loaded.Items;
foreach (Level l in loaded) {
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)
Chat.MessageWhere("Level {0} %Sloaded.", pl => Entities.CanSee(pl, p), lvl.ColoredName);
int physLevel;
if (!int.TryParse(phys, out physLevel)) {
Player.Message(p, "Physics must be an integer between 0 and 5."); return lvl;
}
if (physLevel >= 1 && physLevel <= 5) lvl.setPhysics(physLevel);
int phys = 0;
if (!CommandParser.GetInt(p, physStr, "Physics state", ref phys, 0, 5)) return lvl;
if (phys >= 1 && phys <= 5) lvl.setPhysics(phys);
return lvl;
}

View File

@ -39,11 +39,11 @@ namespace MCGalaxy.Commands.World {
if (args.Length < 5 || args.Length > 6) { Help(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();
if (!UInt16.TryParse(args[1], out x) || !UInt16.TryParse(args[2], out y) || !UInt16.TryParse(args[3], out z)) {
Player.Message(p, "Invalid dimensions."); return false;
}
if (!CommandParser.GetUShort(p, args[1], "Width", ref x)) 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] : "";
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(' ');
Level level = p != null ? p.level : Server.mainLevel;
int state = 0, stateIndex = args.Length == 1 ? 0 : 1;
if (!int.TryParse(args[stateIndex], out state)) {
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;
}
int state = 0, stateIndex = args.Length == 1 ? 0 : 1;
if (!CommandParser.GetInt(p, args[stateIndex], "Physics state", ref state, 0, 5)) return;
if (args.Length == 2) {
level = Matcher.FindLevels(p, args[0]);

View File

@ -43,10 +43,10 @@ namespace MCGalaxy.Commands.World {
Level lvl = Matcher.FindLevels(p, args[0]);
if (lvl == null) return true;
ushort x, y, z;
if (!UInt16.TryParse(args[1], out x) || !UInt16.TryParse(args[2], out y) || !UInt16.TryParse(args[3], out z)) {
Player.Message(p, "Invalid dimensions."); return true;
}
ushort x = 0, y = 0, z = 0;
if (!CommandParser.GetUShort(p, args[1], "Width", ref x)) 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(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) {
bool relative = arg[0] == '~';
if (relative) arg = arg.Substring(1);
value = 0;
if (!int.TryParse(arg, out value)) {
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 (!CommandParser.GetInt(p, arg, axis + " coordinate", ref value, -1024, 1024)) return false;
if (relative) value += (cur / 32);
return true;
}