The great drawop rewrite part 3: The final frontier

This commit is contained in:
UnknownShadow200 2016-08-05 12:43:54 +10:00
parent 687deb946b
commit 34cb2f7c7f
10 changed files with 91 additions and 87 deletions

View File

@ -40,24 +40,24 @@ namespace MCGalaxy.Commands.Building {
return DrawMode.normal; return DrawMode.normal;
} }
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.mode == DrawMode.normal ? 0 : 1;
if (dArgs.mode == DrawMode.solid) return BrushFactory.Find("normal");
if (dArgs.mode == DrawMode.holes) return BrushFactory.Find("checkered");
if (dArgs.mode == DrawMode.random) return BrushFactory.Find("random");
return BrushFactory.Find(p.BrushName);
}
protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
switch (dArgs.mode) { switch (dArgs.Mode) {
case DrawMode.hollow: return new CuboidHollowsDrawOp(); case DrawMode.hollow: return new CuboidHollowsDrawOp();
case DrawMode.walls: return new CuboidWallsDrawOp(); case DrawMode.walls: return new CuboidWallsDrawOp();
case DrawMode.holes: return new CuboidDrawOp(); case DrawMode.holes: return new CuboidDrawOp();
case DrawMode.wire: return new CuboidWireframeDrawOp(); case DrawMode.wire: return new CuboidWireframeDrawOp();
case DrawMode.random: return new CuboidDrawOp(); case DrawMode.random: return new CuboidDrawOp();
} }
return new CuboidDrawOp(); return new CuboidDrawOp();
} }
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.Mode == DrawMode.normal ? 0 : 1;
if (dArgs.Mode == DrawMode.solid) return BrushFactory.Find("normal");
if (dArgs.Mode == DrawMode.holes) return BrushFactory.Find("checkered");
if (dArgs.Mode == DrawMode.random) return BrushFactory.Find("random");
return BrushFactory.Find(p.BrushName);
}
public override void Help(Player p) { public override void Help(Player p) {
Player.Message(p, "%T/cuboid [brush args] <mode>"); Player.Message(p, "%T/cuboid [brush args] <mode>");

View File

@ -43,7 +43,7 @@ namespace MCGalaxy.Commands.Building {
} }
protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
switch (dArgs.mode) { switch (dArgs.Mode) {
case DrawMode.cone: return new AdvConeDrawOp(); case DrawMode.cone: return new AdvConeDrawOp();
case DrawMode.hcone: return new AdvHollowConeDrawOp(); case DrawMode.hcone: return new AdvHollowConeDrawOp();
case DrawMode.icone: return new AdvConeDrawOp(true); case DrawMode.icone: return new AdvConeDrawOp(true);
@ -56,36 +56,34 @@ namespace MCGalaxy.Commands.Building {
case DrawMode.hsphere: return new AdvHollowSphereDrawOp(); case DrawMode.hsphere: return new AdvHollowSphereDrawOp();
case DrawMode.volcano: return new AdvVolcanoDrawOp(); case DrawMode.volcano: return new AdvVolcanoDrawOp();
} }
Help(p); return null; Help(dArgs.Player); return null;
}
protected override bool GetMarks(DrawArgs dArgs, Vec3S32[] m) {
ushort radius = 0, height = 0;
string[] args = dArgs.Message.Split(' ');
AdvDrawOp op = (AdvDrawOp)dArgs.Op;
if ((op.UsesHeight && !CheckTwoArgs(dArgs.Player, ref radius, ref height, args)) ||
(!op.UsesHeight && !CheckOneArg(dArgs.Player, ref radius, args))) return false;
Vec3S32 P = m[0];
m[0] = new Vec3S32(P.X - radius, P.Y, P.Z - radius);
m[1] = new Vec3S32(P.X + radius, P.Y, P.Z + radius);
if (op.UsesHeight) {
m[1].Y += height;
} else {
m[0].Y -= radius; m[1].Y += radius;
}
return true;
} }
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) { protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.Op.UsesHeight ? 3 : 2; brushOffset = ((AdvDrawOp)dArgs.Op).UsesHeight ? 3 : 2;
return BrushFactory.Find(p.BrushName); return BrushFactory.Find(p.BrushName);
} }
protected override bool DoDraw(Player p, Vec3S32[] m, object state, byte type, byte extType) {
ushort radius = 0, height = 0;
string[] args = cpos.message.Split(' ');
if ((op.UsesHeight && !CheckTwoArgs(p, ref radius, ref height, args)) ||
(!op.UsesHeight && !CheckOneArg(p, ref radius, args))) return false;
int brushOffset = op.UsesHeight ? 3 : 2;
Brush brush = ParseBrush(p, cpos, brushOffset);
if (brush == null) return false;
Vec3S32[] marks = {
new Vec3S32(m[0].X - radius, m[0].Y, m[0].Z - radius),
new Vec3S32(m[0].X + radius, m[0].Y, m[0].Z + radius) };
if (op.UsesHeight) {
marks[1].Y += height;
} else {
marks[0].Y -= radius; marks[1].Y += radius;
}
return DrawOp.DoDrawOp(op, brush, p, marks);
}
bool CheckTwoArgs(Player p, ref ushort radius, ref ushort height, string[] parts) { bool CheckTwoArgs(Player p, ref ushort radius, ref ushort height, string[] parts) {
if (parts.Length < 3) { Help(p); return false; } if (parts.Length < 3) { Help(p); return false; }
if (!ushort.TryParse(parts[parts.Length - 3], out height) || height > 2000 || if (!ushort.TryParse(parts[parts.Length - 3], out height) || height > 2000 ||

View File

@ -50,26 +50,26 @@ namespace MCGalaxy.Commands.Building {
if (oldType == Block.custom_block) if (oldType == Block.custom_block)
oldExtType = p.level.GetExtTile(x, y, z); oldExtType = p.level.GetExtTile(x, y, z);
cpos.block = type; cpos.extBlock = extType; cpos.Block = type; cpos.ExtBlock = extType;
if (!Block.canPlace(p, oldType) && !Block.BuildIn(oldType)) { if (!Block.canPlace(p, oldType) && !Block.BuildIn(oldType)) {
Formatter.MessageBlock(p, "fill over ", oldType); return false; Formatter.MessageBlock(p, "fill over ", oldType); return false;
} }
SparseBitSet bits = new SparseBitSet(p.level.Width, p.level.Height, p.level.Length); SparseBitSet bits = new SparseBitSet(p.level.Width, p.level.Height, p.level.Length);
List<int> buffer = new List<int>(), origins = new List<int>(); List<int> buffer = new List<int>(), origins = new List<int>();
FloodFill(p, x, y, z, oldType, oldExtType, cpos.mode, bits, buffer, origins, 0); FloodFill(p, x, y, z, oldType, oldExtType, cpos.Mode, bits, buffer, origins, 0);
int totalFill = origins.Count; int totalFill = origins.Count;
for (int i = 0; i < totalFill; i++) { for (int i = 0; i < totalFill; i++) {
int pos = origins[i]; int pos = origins[i];
p.level.IntToPos(pos, out x, out y, out z); p.level.IntToPos(pos, out x, out y, out z);
FloodFill(p, x, y, z, oldType, oldExtType, cpos.mode, bits, buffer, origins, 0); FloodFill(p, x, y, z, oldType, oldExtType, cpos.Mode, bits, buffer, origins, 0);
totalFill = origins.Count; totalFill = origins.Count;
} }
FillDrawOp op = new FillDrawOp(); FillDrawOp op = new FillDrawOp();
op.Positions = buffer; op.Positions = buffer;
int brushOffset = cpos.mode == DrawMode.normal ? 0 : 1; int brushOffset = cpos.Mode == DrawMode.normal ? 0 : 1;
Brush brush = ParseBrush(p, cpos, brushOffset); Brush brush = ParseBrush(p, cpos, brushOffset);
if (brush == null || !DrawOp.DoDrawOp(op, brush, p, marks)) return false; if (brush == null || !DrawOp.DoDrawOp(op, brush, p, marks)) return false;
bits.Clear(); bits.Clear();

View File

@ -26,11 +26,11 @@ namespace MCGalaxy.Commands.Building {
protected override string PlaceMessage { get { return "Place two blocks to determine the endpoints."; } } protected override string PlaceMessage { get { return "Place two blocks to determine the endpoints."; } }
protected override void OnUse(Player p, string msg, string[] parts, ref DrawArgs dArgs) { protected override void OnUse(Player p, string msg, string[] parts, ref DrawArgs dArgs) {
if (parts.Length < 2 || dArgs.mode == DrawMode.normal) return; if (parts.Length < 2 || dArgs.Mode == DrawMode.normal) return;
string arg = parts[parts.Length - 1]; string arg = parts[parts.Length - 1];
ushort len; ushort len;
if (ushort.TryParse(arg, out len)) if (ushort.TryParse(arg, out len))
dArgs.data = len; dArgs.Data = len;
} }
protected override DrawMode GetMode(string[] parts) { protected override DrawMode GetMode(string[] parts) {
@ -53,8 +53,8 @@ namespace MCGalaxy.Commands.Building {
return DrawMode.normal; return DrawMode.normal;
} }
protected override void GetMarks(DrawArgs dArgs, Vec3S32[] m) { protected override bool GetMarks(DrawArgs dArgs, Vec3S32[] m) {
if (dArgs.mode != DrawMode.straight) return; if (dArgs.Mode != DrawMode.straight) return true;
int dx = Math.Abs(m[0].X - m[1].X), dy = Math.Abs(m[0].Y - m[1].Y), dz = Math.Abs(m[0].Z - m[1].Z); int dx = Math.Abs(m[0].X - m[1].X), dy = Math.Abs(m[0].Y - m[1].Y), dz = Math.Abs(m[0].Z - m[1].Z);
if (dx > dy && dx > dz) { if (dx > dy && dx > dz) {
@ -64,11 +64,12 @@ namespace MCGalaxy.Commands.Building {
} else if (dz > dy && dz > dx) { } else if (dz > dy && dz > dx) {
m[1].X = m[0].X; m[1].Y = m[0].Y; m[1].X = m[0].X; m[1].Y = m[0].Y;
} }
return true;
} }
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) { protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.mode == DrawMode.normal ? 0 : 1; brushOffset = dArgs.Mode == DrawMode.normal ? 0 : 1;
if (dArgs.data != null) brushOffset++; if (dArgs.Data != null) brushOffset++;
return BrushFactory.Find(p.BrushName); return BrushFactory.Find(p.BrushName);
} }

View File

@ -32,16 +32,17 @@ namespace MCGalaxy.Commands.Building {
} }
protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
if (m[0].Y != m[1].Y) { if (m[0].Y != m[1].Y) {
Player.Message(p, "The two edges of the pyramid must be on the same level"); return null; Player.Message(dArgs.Player, "The two edges of the pyramid must be on the same level");
return null;
} }
switch (dArgs.mode) { switch (dArgs.Mode) {
case DrawMode.hollow: return new PyramidHollowDrawOp(); case DrawMode.hollow: return new PyramidHollowDrawOp();
case DrawMode.reverse: return new PyramidReverseDrawOp(); case DrawMode.reverse: return new PyramidReverseDrawOp();
} }
return new PyramidSolidDrawOp(); return new PyramidSolidDrawOp();
} }
public override void Help(Player p) { public override void Help(Player p) {
Player.Message(p, "%T/pyramid [brush args] <mode>"); Player.Message(p, "%T/pyramid [brush args] <mode>");

View File

@ -40,26 +40,27 @@ namespace MCGalaxy.Commands.Building {
return DrawMode.normal; return DrawMode.normal;
} }
protected override void GetMarks(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
Vec3S32 p0 = m[0]; switch (dArgs.Mode) {
Vec3S32 radius = GetRadius(cpos.mode, m);
m[0] = p0 - radius; m[1] = p0 + radius;
}
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.mode == DrawMode.normal ? 0 : 1;
if (dArgs.mode == DrawMode.solid) return BrushFactory.Find("normal");
return BrushFactory.Find(p.BrushName);
}
protected override DrawOp GetDrawOp(DrawArgs dArg, Vec3S32[] m) {
switch (dArgs.mode) {
case DrawMode.hollow: return new AdvHollowSphereDrawOp(); case DrawMode.hollow: return new AdvHollowSphereDrawOp();
case DrawMode.circle: return new EllipsoidDrawOp(); case DrawMode.circle: return new EllipsoidDrawOp();
} }
return new AdvSphereDrawOp(); return new AdvSphereDrawOp();
} }
protected override bool GetMarks(DrawArgs dArgs, Vec3S32[] m) {
Vec3S32 p0 = m[0];
Vec3S32 radius = GetRadius(dArgs.Mode, m);
m[0] = p0 - radius; m[1] = p0 + radius;
return true;
}
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.Mode == DrawMode.normal ? 0 : 1;
if (dArgs.Mode == DrawMode.solid) return BrushFactory.Find("normal");
return BrushFactory.Find(p.BrushName);
}
static Vec3S32 GetRadius(DrawMode mode, Vec3S32[] m) { static Vec3S32 GetRadius(DrawMode mode, Vec3S32[] m) {
int dx = Math.Abs(m[0].X - m[1].X); int dx = Math.Abs(m[0].X - m[1].X);
int dy = Math.Abs(m[0].Y - m[1].Y); int dy = Math.Abs(m[0].Y - m[1].Y);
@ -76,7 +77,7 @@ namespace MCGalaxy.Commands.Building {
return new Vec3S32(0, R, R); return new Vec3S32(0, R, R);
} else { } else {
int R = (int)Math.Sqrt(dx * dx + dy * dy); int R = (int)Math.Sqrt(dx * dx + dy * dy);
return new Vec3S32(R, R, 0); return new Vec3S32(R, R, 0);
} }
} }

View File

@ -28,13 +28,13 @@ namespace MCGalaxy.Commands.Building {
} }
protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) { protected override BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.mode == DrawMode.normal ? 0 : 1; brushOffset = dArgs.Mode == DrawMode.normal ? 0 : 1;
if (dArgs.mode == DrawMode.solid) return BrushFactory.Find("normal"); if (dArgs.Mode == DrawMode.solid) return BrushFactory.Find("normal");
return BrushFactory.Find(p.BrushName); return BrushFactory.Find(p.BrushName);
} }
protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
switch (dArgs.mode) { switch (dArgs.Mode) {
case DrawMode.hollow: return new EllipsoidHollowDrawOp(); case DrawMode.hollow: return new EllipsoidHollowDrawOp();
case DrawMode.vertical: return new CylinderDrawOp(); case DrawMode.vertical: return new CylinderDrawOp();
} }

View File

@ -30,17 +30,18 @@ namespace MCGalaxy.Commands.Building {
get { return "Place a block for the centre, then another for the radius."; } get { return "Place a block for the centre, then another for the radius."; }
} }
protected override void GetMarks(DrawArgs dArgs, Vec3S32[] m) { protected override bool GetMarks(DrawArgs dArgs, Vec3S32[] m) {
int dx = m[0].X - m[1].X, dy = m[0].Y - m[1].Y, dz = m[0].Z - m[1].Z; int dx = m[0].X - m[1].X, dy = m[0].Y - m[1].Y, dz = m[0].Z - m[1].Z;
int horR = (int)Math.Sqrt(dx * dx + dz * dz), verR = Math.Abs(dy); int horR = (int)Math.Sqrt(dx * dx + dz * dz), verR = Math.Abs(dy);
Vec3S32 p0 = m[0]; Vec3S32 p0 = m[0];
m[0] = new Vec3S32(p0.X - horR, p0.Y - verR, p0.Z - horR); m[0] = new Vec3S32(p0.X - horR, p0.Y - verR, p0.Z - horR);
m[1] = new Vec3S32(p0.X + horR, p0.Y + verR, p0.Z + horR); m[1] = new Vec3S32(p0.X + horR, p0.Y + verR, p0.Z + horR);
return true;
} }
protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) { protected override DrawOp GetDrawOp(DrawArgs dArgs, Vec3S32[] m) {
return new TorusDrawOp(); return new TorusDrawOp();
} }
public override void Help(Player p) { public override void Help(Player p) {

View File

@ -31,8 +31,8 @@ namespace MCGalaxy.Commands.Building {
message = message.ToLower(); message = message.ToLower();
string[] parts = message.Split(' '); string[] parts = message.Split(' ');
DrawArgs cpos = default(DrawArgs); DrawArgs cpos = default(DrawArgs);
cpos.message = message; cpos.Message = message;
cpos.mode = GetMode(parts); cpos.Mode = GetMode(parts);
OnUse(p, message, parts, ref cpos); OnUse(p, message, parts, ref cpos);
Player.Message(p, PlaceMessage); Player.Message(p, PlaceMessage);
@ -42,7 +42,7 @@ namespace MCGalaxy.Commands.Building {
protected virtual bool DoDraw(Player p, Vec3S32[] marks, protected virtual bool DoDraw(Player p, Vec3S32[] marks,
object state, byte block, byte extBlock) { object state, byte block, byte extBlock) {
DrawArgs dArgs = (DrawArgs)state; DrawArgs dArgs = (DrawArgs)state;
dArgs.block = block; dArgs.extBlock = extBlock; dArgs.Block = block; dArgs.ExtBlock = extBlock;
DrawOp op = GetDrawOp(dArgs, marks); DrawOp op = GetDrawOp(dArgs, marks);
if (op == null) return false; if (op == null) return false;
@ -63,12 +63,12 @@ namespace MCGalaxy.Commands.Building {
protected virtual void OnUse(Player p, string msg, string[] parts, ref DrawArgs cpos) { } protected virtual void OnUse(Player p, string msg, string[] parts, ref DrawArgs cpos) { }
protected virtual DrawMode GetMode(string[] parts) { return DrawMode.Normal; } protected virtual DrawMode GetMode(string[] parts) { return DrawMode.normal; }
protected virtual void GetMarks(DrawArgs dArgs, Vec3S32[] m) { return m; } protected virtual bool GetMarks(DrawArgs dArgs, Vec3S32[] m) { return true; }
protected virtual BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) { protected virtual BrushFactory GetBrush(Player p, DrawArgs dArgs, ref int brushOffset) {
brushOffset = dArgs.mode == DrawMode.normal ? 0 : 1; brushOffset = dArgs.Mode == DrawMode.normal ? 0 : 1;
return BrushFactory.Find(p.BrushName); return BrushFactory.Find(p.BrushName);
} }
@ -99,26 +99,28 @@ namespace MCGalaxy.Commands.Building {
protected static Brush ParseBrush(Player p, DrawArgs dArgs, protected static Brush ParseBrush(Player p, DrawArgs dArgs,
int usedFromEnd, BrushFactory factory = null) { int usedFromEnd, BrushFactory factory = null) {
int end = dArgs.message.Length; int end = dArgs.Message.Length;
string brushMsg = ""; string brushMsg = "";
for (int i = 0; i < usedFromEnd; i++) { for (int i = 0; i < usedFromEnd; i++) {
end = dArgs.message.LastIndexOf(' ', end - 1); end = dArgs.Message.LastIndexOf(' ', end - 1);
if (end == -1) break; if (end == -1) break;
} }
if (end >= 0) brushMsg = dArgs.message.Substring(0, end); if (end >= 0) brushMsg = dArgs.Message.Substring(0, end);
if (brushMsg == "") brushMsg = p.DefaultBrushArgs; if (brushMsg == "") brushMsg = p.DefaultBrushArgs;
if (factory == null) factory = BrushFactory.Find(p.BrushName); if (factory == null) factory = BrushFactory.Find(p.BrushName);
BrushArgs args = new BrushArgs(p, brushMsg, dArgs.block, dArgs.extBlock); BrushArgs args = new BrushArgs(p, brushMsg, dArgs.Block, dArgs.ExtBlock);
return factory.Construct(args); return factory.Construct(args);
} }
protected struct DrawArgs { protected struct DrawArgs {
public DrawMode mode; public DrawMode Mode;
public byte block, extBlock; public byte Block, ExtBlock;
public object data; public string Message;
public string message;
public object Data;
public DrawOp Op; public DrawOp Op;
public Player Player;
} }
protected enum DrawMode { protected enum DrawMode {

View File

@ -26,8 +26,8 @@ using MCGalaxy.Drawing.Brushes;
namespace MCGalaxy.Drawing.Ops { namespace MCGalaxy.Drawing.Ops {
public abstract class AdvDrawOp : DrawOp { public abstract class AdvDrawOp : DrawOp {
public int Radius { get { return (Max.X - Min.X) / 2; } } public int Radius { get { return (Max.X - Min.X) / 2; } }
public bool Invert; public bool Invert;
public virtual bool UsesHeight { get { return true; } } public virtual bool UsesHeight { get { return true; } }
} }