There's a new class that helps in parsing the command arguments. It's Misc.Message.
- Code: Select all
namespace MCDzienny.Misc
{
public class Message
{
// Represents a position of the reader.
public int Pointer
// Gets the number of arguments.
public int Count
// Constructor that takes the string message as argument.
public Message(string message)
// Reads a next argument as string. If argument doesn't exist it returns null.
public string ReadString()
// Same as ReadString but it returns a lower case string, or null if the argument doesn't exist.
public string ReadStringLower()
// Reads the rest of the arguments and returns them as string. They are seperated by spaces.
// It returns null if there is no next argument.
public string ReadToEnd()
// Returns true if the next argument is an integer number. False otherwise.
public bool IsNextInt()
// It reads the next argument as an integer. It throws exception if the argument doesn't exist,
// or is not a valid integer number.
public int ReadInt()
}
}
There's also a new method Player.ReadLine() that captures the player next chat message.
It can be escaped by a player by using "/a". In this case Player.ReadLine() will return null. Otherwise it will return the player input. Also, player can bypass it by starting his message with a dot. For example ".Hi Jack" message will be sent to global/level chat without the dot i.e. "Hi Jack", but the next statement not starting with a dot will be captured by the Player.ReadLine() method. But the player has to be informed about it, otherwise it's wise to assume they will never use /a or . escape characters on purpose.
Below is an example of a command that uses both mentioned features:
- Code: Select all
namespace MCDzienny
{
public class CmdCone : Command
{
public override string name { get { return "cone"; } }
public override string shortcut { get { return ""; } }
public override string type { get { return "build"; } }
public override bool museumUsable { get { return false; } }
public override LevelPermission defaultRank { get { return LevelPermission.Builder; } }
public override bool ConsoleAccess { get { return false; } }
public override void Use(Player p, string message)
{
Misc.Message msg = new Misc.Message(message);
int radius = 0;
int height = 0;
// If the radius and height values are not specified, ask about them.
if (!msg.IsNextInt())
{
string givenRadius = ReadConeRadius(p);
while (true)
{
if (givenRadius == null)
return;
try
{
radius = int.Parse(givenRadius.Trim());
}
catch
{
Player.SendMessage(p, "Given value is not a number.");
givenRadius = ReadConeRadius(p);
continue;
}
if (radius <= 0)
{
Player.SendMessage(p, "Radius has to be greater than 0.");
givenRadius = ReadConeRadius(p);
continue;
}
break;
}
Player.SendMessage(p, "Cone radius: %a" + radius.ToString());
string givenHeight = ReadConeHeight(p);
while (true)
{
if (givenHeight == null)
return;
try
{
height = int.Parse(givenHeight.Trim());
}
catch
{
Player.SendMessage(p, "Given value is not a number.");
givenHeight = ReadConeHeight(p);
continue;
}
if (height <= 0)
{
Player.SendMessage(p, "Height has to be greater than 0.");
givenHeight = ReadConeHeight(p);
continue;
}
break;
}
Player.SendMessage(p, "Cone height: %a" + height.ToString());
}
else
{
// Try to parse the given radius and height values.
radius = msg.ReadInt();
if (radius <= 0)
{
Player.SendMessage(p, "Incorrect radius value.");
return;
}
if (msg.IsNextInt())
height = msg.ReadInt();
if (height <= 0)
{
Player.SendMessage(p, "Incorrect height value.");
return;
}
}
// Check if a block type was specified. If yes check if the player can place it.
byte block = Block.Zero;
string blockName = msg.ReadString();
if (blockName != null)
{
block = Block.Parse(blockName);
if (block == Block.Zero)
{
Player.SendMessage(p, "Unknown block type: " + blockName);
return;
}
if (!Block.canPlace(p, block))
{
Player.SendMessage(p, "Cannot place this block type.");
return;
}
}
// Capture one block change then call the draw method.
BlockCatch.CaptureOneBlock(p, DrawCone, new ExtendedDrawArgs(block, radius, height));
}
private string ReadConeRadius(Player p)
{
// Get input from the player.
Player.SendMessage(p, "Write cone radius:");
return p.ReadLine();
}
private string ReadConeHeight(Player p)
{
// Get input from the player.
Player.SendMessage(p, "Write cone height:");
return p.ReadLine();
}
private void DrawCone(Player p, ChangeInfo ci, ExtendedDrawArgs da)
{
int radius = da.Integer;
int height = da.Integers[0];
int x = ci.X;
int y = ci.Y;
int z = ci.Z;
// If the block type was given earlier use it, otherwise use the last placed block.
byte block = da.Type1 == Block.Zero ? ci.Type : da.Type1;
if (!Block.canPlace(p, block))
{
Player.SendMessage(p, "Cannot place this block type.");
return;
}
// Draw a cone to the block changes list.
Core.PrepareCone(p, radius, height, x, y, z, block);
// Check if player can change that many blocks. If not abort block changes.
if (p.BlockChanges.Count > p.group.maxBlocks)
{
Player.SendMessage(p, "You tried to change {0} blocks. It's more than your current limit: {1}."
, p.BlockChanges.Count, p.group.maxBlocks);
p.BlockChanges.Abort();
return;
}
// Send block changes.
int blockCount = p.BlockChanges.Count;
p.BlockChanges.Commit();
Player.SendMessage(p, "You've built a cone of radius: {0} and height: {1}, which consists of {2} blocks."
, radius + 1, height, blockCount);
// If the static mode is on, repeat.
if (p.staticCommands)
BlockCatch.CaptureOneBlock(p, DrawCone, da);
}
public override void Help(Player p)
{
Player.SendMessage(p, "/cone - draws a cone.");
Player.SendMessage(p, "For quick drawing:");
Player.SendMessage(p, "/cone [radius] [height] <block>");
Player.SendMessage(p, "/cone <block>");
}
}
}