Now /write works with brushes, more accurate 'selecting X' messages for a few drawops

This commit is contained in:
UnknownShadow200 2018-05-30 11:59:02 +10:00
parent 009556797d
commit 7a23e04531
11 changed files with 97 additions and 105 deletions

View File

@ -21,8 +21,11 @@ using MCGalaxy.Drawing.Ops;
namespace MCGalaxy.Commands.Building {
public sealed class CmdBezier : DrawCmd {
public override string name { get { return "Bezier"; } }
protected override int MarksCount { get { return 3; } }
protected override string SelectionType { get { return "points"; } }
protected override string PlaceMessage { get { return "Place or break two blocks to determine the endpoints, then another for the control point"; } }
public override int MarksCount { get { return 3; } }
public override CommandAlias[] Aliases {
get { return new CommandAlias[] { new CommandAlias("Curve") }; }
}

View File

@ -23,8 +23,10 @@ using MCGalaxy.Maths;
namespace MCGalaxy.Commands.Building {
public sealed class CmdDraw : DrawCmd {
public override string name { get { return "Draw"; } }
protected override int MarksCount { get { return 1; } }
protected override string SelectionType { get { return "origin"; } }
protected override string PlaceMessage { get { return "Place a block to determine the origin."; } }
public override int MarksCount { get { return 1; } }
protected override DrawMode GetMode(string[] parts) {
string msg = parts[0];
@ -59,24 +61,35 @@ namespace MCGalaxy.Commands.Building {
}
if (op == null) { Help(dArgs.Player); return null; }
// Validate radius/height when the user first uses the command
int radius = 0, height = 0;
string[] args = dArgs.Message.SplitSpaces();
if ((op.UsesHeight && !CheckTwoArgs(dArgs.Player, ref radius, ref height, args)) ||
(!op.UsesHeight && !CheckOneArg(dArgs.Player, ref radius, args)))
return null;
AdvDrawMeta meta = new AdvDrawMeta();
bool success = false;
string[] parts = dArgs.Message.SplitSpaces();
Player p = dArgs.Player;
if (op.UsesHeight) {
if (parts.Length < 3) {
Player.Message(p, "You need to provide the radius and the height for the {0}.", parts[0]);
} else {
success = CommandParser.GetInt(p, parts[1], "radius", ref meta.radius, 0, 2000)
&& CommandParser.GetInt(p, parts[2], "height", ref meta.height, 0, 2000);
}
} else {
if (parts.Length < 2) {
Player.Message(p, "You need to provide the radius for the {0}.", parts[0]);
} else {
success = CommandParser.GetInt(p, parts[1], "radius", ref meta.radius, 0, 2000);
}
}
if (!success) return null;
dArgs.Meta = meta;
return op;
}
protected override void GetMarks(DrawArgs dArgs, ref Vec3S32[] m) {
int radius = 0, height = 0;
string[] args = dArgs.Message.SplitSpaces();
AdvDrawOp op = (AdvDrawOp)dArgs.Op;
if ((op.UsesHeight && !CheckTwoArgs(dArgs.Player, ref radius, ref height, args)) ||
(!op.UsesHeight && !CheckOneArg(dArgs.Player, ref radius, args))) {
m = null; return;
}
AdvDrawMeta meta = (AdvDrawMeta)dArgs.Meta;
int radius = meta.radius;
Vec3S32 P = m[0];
m = new Vec3S32[] {
@ -85,7 +98,7 @@ namespace MCGalaxy.Commands.Building {
};
if (op.UsesHeight) {
m[1].Y += height;
m[1].Y += meta.height;
} else {
m[0].Y -= radius; m[1].Y += radius;
}
@ -96,20 +109,7 @@ namespace MCGalaxy.Commands.Building {
dArgs.BrushArgs = dArgs.Message.Splice(argsUsed, 0);
}
bool CheckTwoArgs(Player p, ref int radius, ref int height, string[] parts) {
if (parts.Length < 3) {
Player.Message(p, "You need to provide the radius and the height for the {0}.", parts[0]); return false;
}
return CommandParser.GetInt(p, parts[1], "radius", ref radius, 0, 2000)
&& CommandParser.GetInt(p, parts[2], "height", ref height, 0, 2000);
}
bool CheckOneArg(Player p, ref int radius, string[] parts) {
if (parts.Length < 2) {
Player.Message(p, "You need to provide the radius for the {0}.", parts[0]); return false;
}
return CommandParser.GetInt(p, parts[1], "radius", ref radius, 0, 2000);
}
class AdvDrawMeta { public int radius, height; }
public override void Help(Player p) {
Player.Message(p, "%T/Draw [object] [baseradius] [height] <brush args>");

View File

@ -26,13 +26,15 @@ namespace MCGalaxy.Commands.Building {
public override string name { get { return "Fill"; } }
public override string shortcut { get { return "f"; } }
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
protected override string PlaceMessage { get { return "Place or break a block to mark the area you wish to fill."; } }
public override int MarksCount { get { return 1; } }
public override CommandAlias[] Aliases {
get { return new[] { new CommandAlias("F3D"), new CommandAlias("F2D", "2d"),
new CommandAlias("Fill3D"), new CommandAlias("Fill2D", "2d") }; }
}
protected override int MarksCount { get { return 1; } }
protected override string SelectionType { get { return "origin"; } }
protected override string PlaceMessage { get { return "Place or break a block to mark the area you wish to fill."; } }
protected override DrawMode GetMode(string[] parts) {
if (parts[parts.Length - 1].CaselessEq("confirm")) {
string prev = parts.Length >= 2 ? parts[parts.Length - 2] : "";

View File

@ -24,6 +24,8 @@ namespace MCGalaxy.Commands.Building {
public sealed class CmdLine : DrawCmd {
public override string name { get { return "Line"; } }
public override string shortcut { get { return "l"; } }
protected override string SelectionType { get { return "endpoints"; } }
protected override string PlaceMessage { get { return "Place or break two blocks to determine the endpoints."; } }
protected override DrawMode GetMode(string[] parts) {
@ -91,7 +93,7 @@ namespace MCGalaxy.Commands.Building {
if (dArgs.Mode != DrawMode.wire) return true;
// special for connected line mode
p.MakeSelection(MarksCount, "Selecting region for %S" + dArgs.Op.Name, dArgs, DoDraw);
p.MakeSelection(MarksCount, "Selecting endpoints for %S" + dArgs.Op.Name, dArgs, DoDraw);
Vec3U16 pos = p.lastClick;
p.DoBlockchangeCallback(pos.X, pos.Y, pos.Z, p.GetHeldBlock());
return false;

View File

@ -23,6 +23,7 @@ namespace MCGalaxy.Commands.Building {
public sealed class CmdRainbow : DrawCmd {
public override string name { get { return "Rainbow"; } }
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
protected override void GetBrush(DrawArgs dArgs) { dArgs.BrushName = "normal"; }
protected override DrawOp GetDrawOp(DrawArgs dArgs) {

View File

@ -22,11 +22,9 @@ namespace MCGalaxy.Commands.Building {
public sealed class CmdTriangle : DrawCmd {
public override string name { get { return "Triangle"; } }
public override string shortcut { get { return "tri"; } }
public override int MarksCount { get { return 3; } }
protected override string PlaceMessage {
get { return "Place three blocks to determine the edges."; }
}
protected override int MarksCount { get { return 3; } }
protected override string PlaceMessage { get { return "Place three blocks to determine the edges."; } }
protected override DrawOp GetDrawOp(DrawArgs dArgs) {
return new TriangleDrawOp();

View File

@ -16,56 +16,45 @@
permissions and limitations under the Licenses.
*/
using System;
using MCGalaxy.Drawing.Brushes;
using MCGalaxy.Drawing.Ops;
using MCGalaxy.Maths;
using BlockID = System.UInt16;
namespace MCGalaxy.Commands.Building {
public class CmdWriteText : Command {
public class CmdWriteText : DrawCmd {
public override string name { get { return "WriteText"; } }
public override string shortcut { get { return "wrt"; } }
public override string type { get { return CommandTypes.Building; } }
public override bool museumUsable { get { return false; } }
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
public override bool SuperUseable { get { return false; } }
public override void Use(Player p, string message) {
protected override string SelectionType { get { return "direction"; } }
protected override string PlaceMessage { get { return "Place or break two blocks to determine direction."; } }
protected override DrawOp GetDrawOp(DrawArgs dArgs) {
Player p = dArgs.Player;
if (!p.group.CanExecute("Write")) {
Player.Message(p, "You must be able to use /write to use /writetext."); return;
Player.Message(p, "You must be able to use %T/Write %Sto use %T/WriteText."); return null;
}
if (message.Length == 0) { Help(p); return; }
string[] args = message.SplitSpaces(3);
if (args.Length < 3) { Help(p); return; }
string[] args = dArgs.Message.SplitSpaces(3);
if (args.Length < 3) { Help(p); return null; }
byte scale = 1, spacing = 1;
if (!byte.TryParse(args[0], out scale)) scale = 1;
if (!byte.TryParse(args[1], out spacing)) spacing = 1;
WriteArgs wArgs = new WriteArgs();
wArgs.scale = scale; wArgs.spacing = spacing;
wArgs.message = args[2].ToUpper();
Player.Message(p, "Place or break two blocks to determine direction.");
p.MakeSelection(2, "Selecting direction for %SWrite", wArgs, DoWrite);
}
bool DoWrite(Player p, Vec3S32[] marks, object state, BlockID block) {
WriteArgs wArgs = (WriteArgs)state;
if (marks[0].X == marks[1].X && marks[0].Z == marks[1].Z) {
Player.Message(p, "No direction was selected"); return false;
}
if (!CommandParser.GetByte(p, args[0], "Scale", ref scale)) return null;
if (!CommandParser.GetByte(p, args[1], "Spacing", ref spacing)) return null;
WriteDrawOp op = new WriteDrawOp();
op.Text = wArgs.message;
op.Scale = wArgs.scale; op.Spacing = wArgs.spacing;
Brush brush = new SolidBrush(block);
DrawOpPerformer.Do(op, brush, p, marks);
return true;
op.Scale = scale; op.Spacing = spacing;
op.Text = args[2].ToUpper();
return op;
}
class WriteArgs { public byte scale, spacing; public string message; }
protected override void GetMarks(DrawArgs dArgs, ref Vec3S32[] m) {
if (m[0].X != m[1].X || m[0].Z != m[1].Z) return;
Player.Message(dArgs.Player, "No direction was selected");
m = null;
}
protected override void GetBrush(DrawArgs dArgs) { dArgs.BrushArgs = ""; }
public override void Help(Player p) {
Player.Message(p, "%T/WriteText [scale] [spacing] [message]");

View File

@ -26,8 +26,11 @@ namespace MCGalaxy.Commands.Building {
public override string type { get { return CommandTypes.Building; } }
public override bool museumUsable { get { return false; } }
public override LevelPermission defaultRank { get { return LevelPermission.Builder; } }
public virtual int MarksCount { get { return 2; } }
public override bool SuperUseable { get { return false; } }
protected virtual int MarksCount { get { return 2; } }
protected virtual string SelectionType { get { return "region"; } }
protected virtual string PlaceMessage { get { return "Place or break two blocks to determine the edges."; } }
protected const string BrushHelpLine = " %HFor help about brushes, type %T/Help Brush%H.";
public override void Use(Player p, string message) {
@ -47,7 +50,7 @@ namespace MCGalaxy.Commands.Building {
if (!factory.Validate(bArgs)) return;
Player.Message(p, PlaceMessage);
p.MakeSelection(MarksCount, "Selecting region for %S" + dArgs.Op.Name, dArgs, DoDraw);
p.MakeSelection(MarksCount, "Selecting " + SelectionType + " for %S" + dArgs.Op.Name, dArgs, DoDraw);
}
protected virtual bool DoDraw(Player p, Vec3S32[] marks, object state, BlockID block) {
@ -74,10 +77,6 @@ namespace MCGalaxy.Commands.Building {
return BrushFactory.Find(args.BrushName);
}
protected virtual string PlaceMessage {
get { return "Place or break two blocks to determine the edges."; }
}
protected virtual DrawMode GetMode(string[] parts) { return DrawMode.normal; }
@ -97,6 +96,7 @@ namespace MCGalaxy.Commands.Building {
public DrawOp Op;
public Player Player;
public object Meta;
}
}

View File

@ -47,16 +47,16 @@ namespace MCGalaxy.Drawing.Ops {
return blocks;
}
int dirX, dirZ;
Vec3U16 pos;
Vec3S32 dir, pos;
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) {
Vec3U16 p1 = Clamp(marks[0]), p2 = Clamp(marks[1]);
if (Math.Abs(p2.X - p1.X) > Math.Abs(p2.Z - p1.Z))
dirX = p2.X > p1.X? 1 : -1;
else
dirZ = p2.Z > p1.Z ? 1 : -1;
pos = p1;
Vec3S32 p1 = marks[0], p2 = marks[1];
if (Math.Abs(p2.X - p1.X) > Math.Abs(p2.Z - p1.Z)) {
dir.X = p2.X > p1.X ? 1 : -1;
} else {
dir.Z = p2.Z > p1.Z ? 1 : -1;
}
pos = p1;
foreach (char c in Text) {
DrawLetter(Player, c, brush, output);
}
@ -65,8 +65,7 @@ namespace MCGalaxy.Drawing.Ops {
void DrawLetter(Player p, char c, Brush brush, DrawOpOutput output) {
if ((int)c >= 256 || letters[c] == 0) {
if (c != ' ') Player.Message(p, "\"{0}\" is not currently supported, replacing with space.", c);
pos.X = (ushort)(pos.X + dirX * 4 * Scale);
pos.Z = (ushort)(pos.Z + dirZ * 4 * Scale);
pos += dir * (4 * Scale);
} else {
ulong flags = letters[c]; int shift = 56;
while (flags != 0) {
@ -79,16 +78,14 @@ namespace MCGalaxy.Drawing.Ops {
for (int ver = 0; ver < Scale; ver++)
for (int hor = 0; hor < Scale; hor++)
{
int x = pos.X + dirX * hor, y = pos.Y + j * Scale + ver, z = pos.Z + dirZ * hor;
int x = pos.X + dir.X * hor, y = pos.Y + j * Scale + ver, z = pos.Z + dir.Z * hor;
output(Place((ushort)x, (ushort)y, (ushort)z, brush));
}
}
pos.X = (ushort)(pos.X + dirX * Scale);
pos.Z = (ushort)(pos.Z + dirZ * Scale);
pos += dir * Scale;
}
}
pos.X = (ushort)(pos.X + dirX * Spacing);
pos.Z = (ushort)(pos.Z + dirZ * Spacing);
pos += dir * Spacing;
}
static int CountBits(int value) {

View File

@ -157,7 +157,7 @@
<Compile Include="Commands\building\CmdSphere.cs" />
<Compile Include="Commands\building\CmdTransform.cs" />
<Compile Include="Commands\building\CmdTriangle.cs" />
<Compile Include="Commands\building\ReplaceCmd.cs" />
<Compile Include="Commands\building\ReplaceCmds.cs" />
<Compile Include="Commands\building\CmdRestartPhysics.cs" />
<Compile Include="Commands\building\CmdSpheroid.cs" />
<Compile Include="Commands\building\CmdSpin.cs" />